import java.io.*;
public class Segment{

    public int numAtoms, numBonds, numAngles, numTorsions, numImpropers, numZmatrix, numParms, iParms;

    public AtomDefinition[] atom;
    public BondDefinition[] bond;
    public AngleDefinition[] angle;
    public TorsionDefinition[] torsion;
    public ImproperDefinition[] improper;
    public ZmatrixDefinition[] zmatrix;
    public String title = new String("Segment File Generated by NWChem Java Tool");

    public Segment(){
    };

    void read(String fileName){
	// System.out.println("Reading file "+fileName);
	try{
	    BufferedReader br = new BufferedReader(new FileReader(fileName));
	    String card1;
	    String card2;
	    String card3;
	    String card4;
	    card1=br.readLine();
	    while(card1.startsWith("$") || card1.startsWith("#")){
		if(card1.startsWith("#")) title=card1;
		card1=br.readLine();
	    };
            card1=br.readLine();
	    numAtoms=Integer.parseInt(card1.substring(0,5).trim());
	    numBonds=Integer.parseInt(card1.substring(5,10).trim());
	    numAngles=Integer.parseInt(card1.substring(10,15).trim());
	    numTorsions=Integer.parseInt(card1.substring(15,20).trim());
	    numImpropers=Integer.parseInt(card1.substring(20,25).trim());
	    numZmatrix=Integer.parseInt(card1.substring(25,30).trim());
	    numParms=Integer.parseInt(card1.substring(30,35).trim());
	    iParms=Integer.parseInt(card1.substring(35,40).trim());
	    atom = new AtomDefinition[numAtoms];
	    bond = new BondDefinition[numBonds];
	    angle = new AngleDefinition[numAngles];
	    torsion = new TorsionDefinition[numTorsions];
	    improper = new ImproperDefinition[numImpropers];
	    zmatrix = new ZmatrixDefinition[numZmatrix];
            card1=br.readLine();
	    for(int i=0; i<numAtoms; i++){
		card1=br.readLine();
		card2=br.readLine();
                card3=card2;
                card4=card2;
		if(numParms>1){card3=br.readLine();};
		if(numParms>2){card4=br.readLine();};
		atom[i] = new AtomDefinition(card1,card2,card3,card4);
	    };
	    for(int i=0; i<numBonds; i++){
		card1=br.readLine();
		card2=br.readLine();
                card3=card2;
                card4=card2;
		if(numParms>1){card3=br.readLine();};
		if(numParms>2){card4=br.readLine();};
		bond[i] = new BondDefinition(card1,card2,card3,card4);
	    };
	    for(int i=0; i<numAngles; i++){
		card1=br.readLine();
		card2=br.readLine();
                card3=card2;
                card4=card2;
		if(numParms>1){card3=br.readLine();};
		if(numParms>2){card4=br.readLine();};
		angle[i] = new AngleDefinition(card1,card2,card3,card4);
	    };
	    for(int i=0; i<numTorsions; i++){
		card1=br.readLine();
		card2=br.readLine();
                card3=card2;
                card4=card2;
		if(numParms>1){card3=br.readLine();};
		if(numParms>2){card4=br.readLine();};
		torsion[i] = new TorsionDefinition(card1,card2,card3,card4);
	    };
	    for(int i=0; i<numImpropers; i++){
		card1=br.readLine();
		card2=br.readLine();
                card3=card2;
                card4=card2;
		if(numParms>1){card3=br.readLine();};
		if(numParms>2){card4=br.readLine();};
		improper[i] = new ImproperDefinition(card1,card2,card3,card4);
	    };
	    for(int i=0; i<numZmatrix; i++){
		card1=br.readLine();
		zmatrix[i] = new ZmatrixDefinition(card1);
	    };
	    br.close();
	} catch(Exception e) {e.printStackTrace();};
    };

    public void order(){
	int itemp;
	for(int i=0; i<numBonds; i++){
	    if(bond[i].atomi>bond[i].atomj){
		itemp=bond[i].atomi; bond[i].atomi=bond[i].atomj; bond[i].atomj=itemp;
	    };
	};
	for(int i=0; i<numAngles; i++){
	    if(angle[i].atomi>angle[i].atomk){
		itemp=angle[i].atomi; angle[i].atomi=angle[i].atomk; angle[i].atomk=itemp;
	    };
	};
	for(int i=0; i<numTorsions; i++){
	    if(torsion[i].atomj>torsion[i].atomk){
		itemp=torsion[i].atomi; torsion[i].atomi=torsion[i].atoml; torsion[i].atoml=itemp;
		itemp=torsion[i].atomj; torsion[i].atomj=torsion[i].atomk; torsion[i].atomk=itemp;
	    };
	};
	BondDefinition btemp;
	for(int i=0; i<numBonds-1; i++){
	    for(int j=i+1; j<numBonds; j++){
		if(bond[i].atomi>bond[j].atomi || (bond[i].atomi==bond[j].atomi && bond[i].atomj>bond[j].atomj)){
		    btemp=bond[i]; bond[i]=bond[j]; bond[j]=btemp;
		};
	    };
	};
	AngleDefinition atemp;
	for(int i=0; i<numAngles-1; i++){
	    for(int j=i+1; j<numAngles; j++){
		if(angle[i].atomj>angle[j].atomj || 
		   (angle[i].atomj==angle[j].atomj && angle[i].atomi>angle[j].atomi) ||
		   (angle[i].atomj==angle[j].atomj && angle[i].atomi==angle[j].atomi && angle[i].atomk>angle[j].atomk)){
		    atemp=angle[i]; angle[i]=angle[j]; angle[j]=atemp;
		};
	    };
	};
	TorsionDefinition ttemp;
	for(int i=0; i<numTorsions-1; i++){
	    for(int j=i+1; j<numTorsions; j++){
		if(torsion[i].atomj>torsion[j].atomj || 
		   (torsion[i].atomj==torsion[j].atomj && torsion[i].atomk>torsion[j].atomk) ||
		   (torsion[i].atomj==torsion[j].atomj && torsion[i].atomk==torsion[j].atomk && torsion[i].atomi>torsion[j].atomi) ||
		   (torsion[i].atomj==torsion[j].atomj && torsion[i].atomk==torsion[j].atomk && 
		    torsion[i].atomi==torsion[j].atomi && torsion[i].atoml>torsion[j].atoml)){
		    ttemp=torsion[i]; torsion[i]=torsion[j]; torsion[j]=ttemp;
		};
	    };
	};;
	ImproperDefinition otemp;
	for(int i=0; i<numImpropers-1; i++){
	    for(int j=i+1; j<numImpropers; j++){
		if(improper[i].atomk>improper[j].atomk || 
		   (improper[i].atomk==improper[j].atomk && improper[i].atoml>improper[j].atoml) ||
		   (improper[i].atomk==improper[j].atomk && improper[i].atoml==improper[j].atoml && improper[i].atomi>improper[j].atomi) ||
		   (improper[i].atomk==improper[j].atomk && improper[i].atoml==improper[j].atoml && 
		    improper[i].atomi==improper[j].atomi && improper[i].atomj>improper[j].atomj)){
		    otemp=improper[i]; improper[i]=improper[j]; improper[j]=otemp;
		};
	    };
	};
    };

    public void write(String filename){
	try{
	    PrintfWriter file = new PrintfWriter(new FileWriter(filename));
	    file.println(title);
	    file.println("   4.600000");
	    file.printf("%5d",numAtoms);
	    file.printf("%5d",numBonds);
	    file.printf("%5d",numAngles);
	    file.printf("%5d",numTorsions);
	    file.printf("%5d",numImpropers);
	    file.printf("%5d",numZmatrix);
	    file.printf("%5d",3);
	    file.printf("%5d",1);
	    file.println();
	    file.println("    0.000000");
	    for(int i=0; i<numAtoms; i++){
		file.printf("%5d",i+1);
		file.print(atom[i].Name+" ");
		file.printf("%5d",atom[i].link);
		file.printf("%5d",atom[i].type);
		file.printf("%5d",0);
		file.printf("%5d",atom[i].cgroup);
		file.printf("%5d",atom[i].pgroup);
		file.println();
		file.print("     "+atom[i].Type1);
		file.printf("%12.6f",atom[i].q1);
		file.printf("%12.5E",atom[i].p1);
		file.println();
		file.print("     "+atom[i].Type2);
		file.printf("%12.6f",atom[i].q2);
		file.printf("%12.5E",atom[i].p2);
		file.println();
		file.print("     "+atom[i].Type3);
		file.printf("%12.6f",atom[i].q3);
		file.printf("%12.5E",atom[i].p3);
		file.println();
	    };
	    for(int i=0; i<numBonds; i++){
		file.printf("%5d",i+1);
		file.printf("%5d",bond[i].atomi);
		file.printf("%5d",bond[i].atomj);
		file.printf("%5d",bond[i].type);
		file.printf("%3d",bond[i].source1);
		file.printf("%1d",bond[i].source1);
		file.printf("%1d",bond[i].source1);
		file.println();
		file.printf("%12.6f",bond[i].bond1);
		file.printf("%12.5E",bond[i].force1);
		file.println();
		file.printf("%12.6f",bond[i].bond2);
		file.printf("%12.5E",bond[i].force2);
		file.println();
		file.printf("%12.6f",bond[i].bond3);
		file.printf("%12.5E",bond[i].force3);
		file.println();
	    };
	    for(int i=0; i<numAngles; i++){
		file.printf("%5d",i+1);
		file.printf("%5d",angle[i].atomi);
		file.printf("%5d",angle[i].atomj);
		file.printf("%5d",angle[i].atomk);
		file.printf("%5d",angle[i].type);
		file.printf("%3d",angle[i].source1);
		file.printf("%1d",angle[i].source1);
		file.printf("%1d",angle[i].source1);
		file.println();
		file.printf("%10.6f",angle[i].angle1);
		file.printf("%12.5E",angle[i].force1);
		file.println();
		file.printf("%10.6f",angle[i].angle2);
		file.printf("%12.5E",angle[i].force2);
		file.println();
		file.printf("%10.6f",angle[i].angle3);
		file.printf("%12.5E",angle[i].force3);
		file.println();
	    };
	    for(int i=0; i<numTorsions; i++){
		file.printf("%5d",i+1);
		file.printf("%5d",torsion[i].atomi);
		file.printf("%5d",torsion[i].atomj);
		file.printf("%5d",torsion[i].atomk);
		file.printf("%5d",torsion[i].atoml);
		file.printf("%5d",torsion[i].type);
		file.printf("%3d",torsion[i].source1);
		file.printf("%1d",torsion[i].source1);
		file.printf("%1d",torsion[i].source1);
		file.println();
		file.printf("%3d",torsion[i].multi1);
		file.printf("%10.6f",torsion[i].torsion1);
		file.printf("%12.5E",torsion[i].force1);
		file.println();
		file.printf("%3d",torsion[i].multi2);
		file.printf("%10.6f",torsion[i].torsion2);
		file.printf("%12.5E",torsion[i].force2);
		file.println();
		file.printf("%3d",torsion[i].multi3);
		file.printf("%10.6f",torsion[i].torsion3);
		file.printf("%12.5E",torsion[i].force3);
		file.println();
	    };
	    for(int i=0; i<numImpropers; i++){
		file.printf("%5d",i+1);
		file.printf("%5d",improper[i].atomi);
		file.printf("%5d",improper[i].atomj);
		file.printf("%5d",improper[i].atomk);
		file.printf("%5d",improper[i].atoml);
		file.printf("%5d",improper[i].type);
		file.printf("%3d",improper[i].source1);
		file.printf("%1d",improper[i].source1);
		file.printf("%1d",improper[i].source1);
		file.println();
		file.printf("%3d",improper[i].multi1);
		file.printf("%10.6f",improper[i].improper1);
		file.printf("%12.5E",improper[i].force1);
		file.println();
		file.printf("%3d",improper[i].multi2);
		file.printf("%10.6f",improper[i].improper2);
		file.printf("%12.5E",improper[i].force2);
		file.println();
		file.printf("%3d",improper[i].multi3);
		file.printf("%10.6f",improper[i].improper3);
		file.printf("%12.5E",improper[i].force3);
		file.println();
	    };
	    for(int i=0; i<numZmatrix; i++){
		file.printf("%5d",i+1);
		file.printf("%5d",zmatrix[i].atomi);
		file.printf("%5d",zmatrix[i].atomj);
		file.printf("%5d",zmatrix[i].atomk);
		file.printf("%5d",zmatrix[i].atoml);
		file.printf("%12.6f",zmatrix[i].bond);
		file.printf("%12.6f",zmatrix[i].angle);
		file.printf("%12.6f",zmatrix[i].torsion);
		file.println();
	    };
	    file.close();
	} catch (Exception ee) { ee.printStackTrace(); };
    };
}
