import java.io.*;
import java.util.*;

public class RandomCoil {
	public HashMap<String, Double> rcoil = new HashMap<String, Double>();  // iupac:atomname - random coil
	protected ArrayList<String[]> restypeAtomStringList = new ArrayList<String[]>();  // iupac - atomname
	public String rc_id = "1";  


	protected class innerRcoil {
		protected String rcoilID;  // SiX different Rcoils
		protected String iupac;
		protected String atomname;
		protected Double rcoilValue;
		
		protected innerRcoil(String rcid, String i, String a, Double r) {
            rcoilID = rcid;
			iupac = i;
			atomname = a;
			rcoilValue = r;
		}
		
		public String[] getRestypeAtomStringArray(){
			String[] s = new String[] {iupac, atomname};
			return s;
		}
	}
	
	public RandomCoil() {		
                   ;
        }

	public void loadRandomCoil() {		

        // change path as absolute path
        String SHIFTXP_DIR = ShiftXp.SHIFTX2_DIR;

		String filename = SHIFTXP_DIR + "/lib/RandomCoil.csv";
		String objFilename = SHIFTXP_DIR + "/lib/RandomCoil.osf";
		String objAtomListname = SHIFTXP_DIR + "/lib/RCoilAtomlist.osf";
		
		
		File f = new File(objFilename);
		File f2 = new File(objAtomListname);
		
		if (f.exists() && f2.exists()) {
			System.out.println("Loading Random Coil ....");
			readHashObjectFile(objFilename);  // set rcoil

			System.out.println("Reading Atom Information ....");
			readArrayListObjectFile(objAtomListname); // set restypeAtomStringList
						
		//	System.out.println("**********\n rcoil:" + rcoil.size() +"\n**********");
		//	System.out.println("**********\n restypeAtomStringList:" + restypeAtomStringList.size() +"\n**********");
		} else {
			f = new File(filename);
			if(!f.exists()){
				System.err.println("Missing [RandomCoil.csv] file");
				System.exit(-1);
			}
			
			innerRcoil rc; 	
			try{
				System.out.println("Reading Atom Information with Making files....");
				
				BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(filename))));
				String line;
				String[] fields;
				
				while(br.ready()){
					line = br.readLine();
					fields = line.split(",");
					// rc_id, iupac, atomname, randomCoil
					rc = new innerRcoil(fields[0].trim(), fields[1].trim(), fields[2].trim(), Double.parseDouble(fields[3].trim()));

					rcoil.put((rc.rcoilID +':'+ rc.iupac +':'+ rc.atomname), rc.rcoilValue); // Hashmap for Search

					// System.out.println("rcoil\t:"+rc.rcoilID +':'+ rc.iupac +':'+ rc.atomname+':'+rc.rcoilValue); // Hashmap for Search

					// append atomanme list
					if ( rc.rcoilID.equals("1") )
					     restypeAtomStringList.add(rc.getRestypeAtomStringArray());
					
				}
				br.close();
				
				// save object into object file format for speed up
				saveObjectFile(objFilename, rcoil);
				saveObjectFile(objAtomListname, restypeAtomStringList);

			} catch(IOException ex){
				ex.printStackTrace();
			}
		}

	}	 
	
	public void setRCoilID(String id)  {
	       this.rc_id = id;
	}

	public void saveObjectFile(String fname, Object obj) {
		try	{
			FileOutputStream fos = new FileOutputStream( fname );
			ObjectOutputStream oos = new ObjectOutputStream( fos );
			oos.writeObject(obj);
			oos.close();		
		} catch (Exception e) {
			// If something unexpected happened, print exception information and quit 
			e.printStackTrace();
			System.exit(1);
		}
	}
	
    @SuppressWarnings({"unchecked"})
	public void readHashObjectFile(String fname) {		
		try	{
			// Deserialization - ObjectOutputStream
			ObjectInputStream ohs = new ObjectInputStream(new BufferedInputStream(new FileInputStream(fname)));			 
			rcoil = (HashMap<String, Double>) ohs.readObject();
			ohs.close();
		} catch (Exception e) {
			// If something unexpected happened, print exception information and quit 
			e.printStackTrace();
			System.exit(1);
		}
	}	
	
    @SuppressWarnings({"unchecked"})
	public void readArrayListObjectFile(String fname)  {
		try	{
			// Deserialization - ObjectOutputStream
			ObjectInputStream ohs = new ObjectInputStream(new BufferedInputStream(new FileInputStream(fname)));			 
			restypeAtomStringList = (ArrayList<String[]>) ohs.readObject();
			ohs.close();
		} catch (Exception e) {
			// If something unexpected happened, print exception information and quit 
			e.printStackTrace();
			System.exit(1);
		}
	}	
		
	public double getRCoil(String iupac, String atomname) {
	        Double rc;
		String key;

	        key = rc_id+':'+iupac+':'+atomname;
               /*** 20100907
                if ( rc_id.equals("1") )  
		     key = rc_id+':'+iupac+':'+atomname;
		else {
		     if  ( ("HA,H,HA2,HA3,N,CA,CB,C".contains(atomname) ) ) 
		            key = rc_id+':'+iupac+':'+atomname;
		     else   key = "1:"+ iupac+':'+atomname;
		}
               ***/

		rc = rcoil.get(key);
		if ( rc == null )  rc = 0.0; 

		return rc;
	}
		
	// Set atoms for each residues to predict and print out atom's chemical shift  
	public ArrayList<String> getAtoms(String restype)  { //throws Exception
		boolean flag = false;
		ArrayList<String> atomList = new ArrayList<String>();

		for ( int i = 0;  i < restypeAtomStringList.size(); i++ ) {			
			if ( restypeAtomStringList.get(i)[0].equals(restype) ) {
				flag = true;
				atomList.add(restypeAtomStringList.get(i)[1]);
			} else {				
				if (flag == true) { 
					break;						
				}				
			}			
		}

		return atomList;			
	}		

	public ArrayList<String> getAtoms(String restype, String atomtype)  { //throws Exception
		boolean flag = false;
		ArrayList<String> atomList = new ArrayList<String>();

                if (atomtype.equals("BACKBONE")) {
                    if (!restype.equals("P")) atomList.add("H");
                    atomList.add("HA");
                    atomList.add("C");
                    atomList.add("CA");
                    if (!restype.equals("G")) atomList.add("CB");
                    if (!restype.equals("P")) atomList.add("N");

                } else if (atomtype.equals("SIDECHAIN")) {
                    for ( int i = 0;  i < restypeAtomStringList.size(); i++ ) {			
                            if ( restypeAtomStringList.get(i)[0].equals(restype) ) {
                                    flag = true;
                                    if (! "H,HA,C,CA,CB,N,HA2,HA3".contains(restypeAtomStringList.get(i)[1]) )  {
                                        atomList.add(restypeAtomStringList.get(i)[1]);
                                        //  System.out.println("restypeatomlist:"+restypeAtomStringList.get(i)[1]);
                                    } else {
                                        // System.out.println("removed backbone atom restypeatomlist:"+restypeAtomStringList.get(i)[1]);
                                    }
                            } else {				
                                    if (flag == true) { 
                                            break;						
                                    }				
                            }			
                    }
                           

                } else {
                    for ( int i = 0;  i < restypeAtomStringList.size(); i++ ) {			
                            if ( restypeAtomStringList.get(i)[0].equals(restype) ) {
                                    flag = true;
                                    //  System.out.println("restypeatomlist:"+restypeAtomStringList.get(i)[1]);
                                    atomList.add(restypeAtomStringList.get(i)[1]);
                            } else {				
                                    if (flag == true) { 
                                            break;						
                                    }				
                            }			
                    }
                }

		return atomList;			
	}		
	
}
