import java.awt.*;
import java.text.*;
import java.io.*;
import java.lang.*;
import myutil.*;
import ccj.*;

class KeyObj
{
    String key;
    Object obj;
}

class SortedTable
{
    int n;
    int m;
    KeyObj[] objArray;

    int curr;

    public SortedTable()
    {
	n = 2;
	m = 1;
	curr = -1;
	objArray = new KeyObj[2];
	objArray[0] = new KeyObj();
	objArray[0].key = "";
	objArray[0].obj = null;
	objArray[1] = null;
    }

    void resize()
    {
	int j, jj, n1;
	KeyObj[] objArray1;

	n1 = 2*m + 1;
	objArray1 = new KeyObj[n1+1];

	jj = 0;
	for (j=0; j<n; j++) {
	    if (objArray[j] != null) {
		objArray1[jj] = objArray[j];
		objArray1[jj+1] = null;
		jj += 2;
	    }
	}

	for ( ; jj<=n1; jj++) {objArray1[jj] = null;}

	objArray = objArray1;
	n = n1;
    }

    public void print()
    {
	int j;

	for (j=0; j<n; j++) {
	    System.out.print(j+": ");
	    if (objArray[j] != null) {
		System.out.println(objArray[j].key);
	    } else {
		System.out.println();
	    }
	}
    }

    public void add(String key, Object obj)
    {
	int right, left, j;
	lookUp(key);
	if ( !objArray[curr].key.equals(key) ) {
	    KeyObj ko = new KeyObj();
	    ko.key = key;
	    ko.obj = obj;

	    left = curr;
	    right = next(left);
	    if (right - left > 1) {
		curr = (right + left)/2;
		objArray[curr] = ko;
	    } else {
		for (j=right+1; j<n; j++) { // find hole 
		    if (objArray[j] == null) { break; }
		}
		for (curr=j; curr>right; curr--) { // shift 
		    objArray[curr] = objArray[curr-1];
		}
		objArray[right] = ko;       // fill hole 
	    }
	    m++;
	}

	if (m/(double)n > 0.7 || m/(double)n < 0.3) {resize();}
	if (objArray[n-1] != null) {resize();}
    }

    public void delete(String key)
    {
	lookUp(key);
	if ( objArray[curr].key.equals(key) ) {
	    objArray[curr] = null;
	}

	if (m/(double)n > 0.7 || m/(double)n < 0.3) {resize();}
	if (objArray[0] == null) resize();
    }

    public Object next()
    {
	for ( curr++; curr<n && objArray[curr]==null; curr++) {}
	if (curr < n) { return objArray[curr].obj; }
	else          { curr=n-1; return null; }
    }

    public Object prev()
    {
	for ( curr--; curr>=0 && objArray[curr]==null; curr--) {}
	if (curr >= 0) { return objArray[curr].obj; }
	else           { curr = 0; return null; }
    }

    int next(int j)
    {
	for ( j++; j<n && objArray[j]==null; j++) {}
	return j;
    }

    int prev(int j)
    {
	for ( j--; j>=0 && objArray[j]==null; j--) {}
	return j;
    }

	/*******************************************
	* Sets class variable curr to index at which
	* key is found and returns object to calling
	* routine.
	*******************************************/

    public Object lookUp(String key)
    {
        int low, mid=0, high;
	KeyObj ko=null;

        low = 0; 
	high = prev(n-1);
        while ( low <= high ) {
	    mid = (low+high)/2;
	    ko = objArray[mid];
	    if (ko == null) {
		mid = prev(mid);
		ko = objArray[mid];
	    }

            if ( key.compareTo(ko.key) < 0 ) {
		high = prev(mid);
            } else 
	    if ( key.compareTo(ko.key) > 0 ) {
		low = next(mid);
            } else {
		curr = mid;
                return ko.obj;  // found it
            }
        }

	curr = high;
	return objArray[high].obj;  // not found
    }
}

class PUData 
{
    String name;
    String dept;
    String email;
    String phone;
    String addr;
}

public class PUSortTable
{
    public static void main(String[] args)
    {
	PUFrame puf = new PUFrame();
	puf.show();
    }
}

class PUFrame extends Frame
{
    static SortedTable st;

    TextField inField    ;
    TextField outField   ;
    TextField nameField  ;
    TextField addrField  ;
    TextField phoneField ;
    TextField emailField ;
    TextField deptField  ;

    public PUFrame()
    {
	st = new SortedTable();

	GridPanel iop = new GridPanel("Courier", 24);
	GridPanel pup = new GridPanel("Courier", 24);
	GridPanel ap  = new GridPanel("Courier", 24);

	iop.add(new Label("Input File: "),  1, 1);
	iop.add(new Label("Output File: "), 1, 2);
	pup.add(new Label("Name: "),        1, 3);
	pup.add(new Label("Address: "),     1, 4);
	pup.add(new Label("Phone: "),       1, 5);
	pup.add(new Label("Email: "),       1, 6);
	pup.add(new Label("Department: "),  1, 7);

	inField    = new TextField("pu_names.dat", 15);
	outField   = new TextField("", 15);
	nameField  = new TextField("", 40);
	addrField  = new TextField("", 40);
	phoneField = new TextField("", 40);
	emailField = new TextField("", 40);
	deptField  = new TextField("", 40);

	iop.add(inField,    2, 1);
	iop.add(outField,   2, 2);
	pup.add(nameField,  2, 3);
	pup.add(addrField,  2, 4);
	pup.add(phoneField, 2, 5);
	pup.add(emailField, 2, 6);
	pup.add(deptField,  2, 7);

	iop.add(new Button("Read"),  3,1);
	iop.add(new Button("Write"), 3,2);

	ap.add(new Button("Look Up"), 1,1);
	ap.add(new Button("Previous"), 2,1);
	ap.add(new Button("Next"), 3,1);
	ap.add(new Button("Add"), 1,2);
	ap.add(new Button("Change"), 2,2);
	ap.add(new Button("Delete"), 3,2);
	ap.add(new Button("Exit"), 4,2);

	setLayout(new BorderLayout(10,10));
	add("North",  iop);
	add("Center", pup);
	add("South",   ap);

	resize(500, 300);
    }

    public boolean action(Event evt, Object arg)
    {
	if (arg.equals("Read")) {
	    readData(inField.getText());
	} else
	if (arg.equals("Write")) {
	    /*
	    writeData(inField.getText());
	    */
	} else
	if (arg.equals("Look Up")) {
	    lookUp(); 
	} else
	if (arg.equals("Previous")) {
	    previous(); 
	} else
	if (arg.equals("Next")) {
	    next(); 
	} else
	if (arg.equals("Add")) {
	    add();
	} else
	if (arg.equals("Change")) {
	    change();
	} else
	if (arg.equals("Delete")) {
	    delete();
	} else
	if (arg.equals("Exit")) {
	    // dispose();
	    System.exit(0);
	} else {
	    return super.action(evt, arg);
	}

	return true;
    }

    static void readData(String fname)
    {
	int i;
	String line=null;
	String full, last, first;

	BufferedReader in;
	try { in = new BufferedReader(new FileReader(fname)); }
	catch (FileNotFoundException fe) 
	{ System.err.println("File not found"); return; }

	PUData    p  = new PUData();
	for (i=0; ; i++) {
	    if (i%500 == 0) {System.out.println(i);}

	    try { line = in.readLine(); } 
	    catch (IOException e) {System.err.println("IO Error");}

	    if (line == null) break;

	    int j = line.indexOf(":")+2;
	    int k = line.length();

	    if (line.startsWith("            name: ")) {
		full = line.substring(j,k).trim();
		k = full.lastIndexOf(' ');
		last  = full.substring(k+1,full.length());
		first = full.substring(0,k);
		p.name = last + ", " + first;
	    } else
	    if (line.startsWith("           phone: ")) {
		p.phone = line.substring(j,k);
	    } else
	    if (line.startsWith("         address: ")) {
		p.addr = line.substring(j,k);
	    } else
	    if (line.startsWith("      department: ")) {
		p.dept = line.substring(j,k);
	    } else
	    if (line.startsWith("           email: ")) {
		p.email = line.substring(j,k);
	    } else
	    if (line.startsWith("------------------")) {
		if (p.name != null) {
		    PUData pp = (PUData) st.lookUp(p.name);
		    if ( pp==null || !pp.name.equals(p.name) ) {
			// System.out.println("adding "+p.name+"\n");
			st.add(p.name, p);
		    }
		    p = new PUData();
		}
	    } 
	}
	// st.print();
    }

    void lookUp() {
	PUData info;
	String name = nameField.getText();
	info = (PUData) st.lookUp(name);

	if (info == null) {
	    info = (PUData) st.next();
	}

	if (info != null) {
	    nameField.setText(info.name);
	    addrField.setText(info.addr);
	    phoneField.setText(info.phone);
	    emailField.setText(info.email);
	    deptField.setText(info.dept);
	}
    }

    void add()
    {
	PUData p = new PUData();

	p.name = nameField.getText();
	p.addr = addrField.getText();
	p.email = emailField.getText();
	p.phone = phoneField.getText();
	p.dept = deptField.getText();

	st.add(p.name, p);
    }

    void delete()
    {
	String name = nameField.getText();;
	st.delete(name);
    }

    void change()
    {
	delete();
	add();
    }

    void previous() {
	PUData info = (PUData) st.prev();

	/*
	if (info == null) {
	    info = (PUData) st.next();
	}
	*/

	if (info != null) {
	    nameField.setText(info.name);
	    addrField.setText(info.addr);
	    phoneField.setText(info.phone);
	    emailField.setText(info.email);
	    deptField.setText(info.dept);
	}
    }

    void next() {
	PUData info = (PUData) st.next();

	/*
	if (info == null) {
	    info = (PUData) st.next();
	}
	*/

	if (info != null) {
	    nameField.setText(info.name);
	    addrField.setText(info.addr);
	    phoneField.setText(info.phone);
	    emailField.setText(info.email);
	    deptField.setText(info.dept);
	}
    }
} 
