package glycoMain;

import static glycoMain.UsualFunctions.*;

import java.util.ArrayList;
import java.util.Hashtable;

import glycoMain.SectionRep;
import glycoMain.SectionUnd;

import glycoMain.Formatting;
import glycoMain.CreateTabResTerm;
import glycoMain.Residue;
import glycoMain.ResidueTerm;
import glycoMain.EnzymeProperties;

public class SugarDigestion {

	String inputSugar;
	String outputSugar;
	EnzymeProperties dico;
	ArrayList<String> enz;
	Hashtable<String, Integer> section;
	boolean unkLink;
	
	ArrayList<String> res;		//the first res array
	ArrayList<String> lin;		//the first lin array
	String rep;
	String und;
	ArrayList<String> undParent;
	boolean changeInRep;
	
	public SugarDigestion(String sugar, EnzymeProperties dico, ArrayList<String> enz, Hashtable<String, Integer> section, boolean unklink){
		this.inputSugar = sugar;
		this.dico = dico;
		this.enz  = enz;
		this.section = section;
		this.unkLink = unklink;
		res = new ArrayList<String>();						//array of the residues
		lin = new ArrayList<String>();						//array of the links
		rep = "";											//string with the section REP
		und = "";
		outputSugar = "";
		undParent = new ArrayList<String>();
		changeInRep = false;
	}
	
	public void createParts (){
		//TODO a revoir ça... mais pour l'instant je suppose que c'est OK
		/*
		 * DIVIDE THE SUGAR AND CREATE PARTS RES, LIN, REP
		 * fill the array 'RES' and 'LIN' and the string 'REP'
		 */
			int oneres = oneResidueFromString(inputSugar, 1);
			System.out.println("create_parts - one res : " + oneres);
			if (oneres == 0){
				String[] spR = inputSugar.split("LIN", 2);
				String[] resid = spR[0].split("\n");
				String[] l = new String[500];
				
				if (section.get("REP") == 1 && section.get("UND") == 0){
					String[] spRep = spR[1].split("REP\n");
					l = spRep[0].split("\n");
					rep = spRep[1];
				}
				else if(section.get("REP") == 0 && section.get("UND") == 1){
					String[] spUnd = spR[1].split("UND\n");
					l = spUnd[0].split("\n");
					und = spUnd[1];		
				}
				else
					l = spR[1].split("\n");		
				
				for (int i = 1; i<resid.length; i++)
					res.add(resid[i]);
				for (int i = 1; i<l.length; i++)
					lin.add(l[i]);			
			}
			if (oneres == 1){
				String[] spR = inputSugar.split("RES\n");
				res.add(spR[1].trim());
			}
			if (oneres == 2){
				String[] spR = inputSugar.split("REP\n");
				res.add(spR[0].split("\n")[1]);
				rep = spR[1];
			}
	}

	public void clearArray(ArrayList<Residue> tab_res, ArrayList<ResidueTerm> tab_res_term, Hashtable<String, Integer> term) {
		/*
		 * CLEAR THE ARRAYS AND MAP
		 */
		tab_res.clear();
		tab_res_term.clear();
		term.clear();		
	}
	
	@SuppressWarnings("rawtypes")
	public void createTabResTerm(ArrayList r, ArrayList l, ArrayList tab_res, ArrayList tab_res_term, Hashtable term){
		/*
		 * CALL ANOTHER CLASS WHICH CREATE 'tab_res_term' : AN ARRAY WITH THE RESIDUE TO CUT
		 */
		System.out.println("Test unklink : " + unkLink);
		CreateTabResTerm creat = new CreateTabResTerm(r, l, dico, enz, tab_res, tab_res_term, term, unkLink);
		creat.beginToTab_res_term();
		tab_res = creat.getTab_res();
		tab_res_term = creat.getTab_res_term(); 
		term = creat.getTerm();
	}	
	public void removeResAndLink(ArrayList<String> l, ArrayList<String> r, ArrayList<Residue> tab_res, ArrayList<ResidueTerm> tab_res_term){
		/*
		 * REMOVE THE RESIDUE AND THE LINK GIVEN BY 'tab_res_term'
		 */	
		ResidueTerm residTerm = tab_res_term.get(0);
		ArrayList<String> rtemp = residTerm.getR();
		ArrayList<String> ltemp = residTerm.getL();
		if (und.isEmpty() || !und.isEmpty() && !undParent.contains(rtemp.get(0))){		
			for (int i=0; i<rtemp.size(); i++){
				for (int j=0; j<r.size(); j++){
					if (r.get(j).startsWith(rtemp.get(i)))	{
						r.remove(r.get(j));				
						break;
					}
				}
			}
			for (int j=0; j<l.size(); j++){
				for (int i=0; i<ltemp.size(); i++){	
					if (l.get(j).contains("(" + ltemp.get(i)+")" + rtemp.get(i))){
						System.out.println(l.get(j));
						l.remove(l.get(j));	

					}
				}
			}
		}
		else{
			tab_res_term.remove(0);
		}
	}

	public boolean stopLoop(ArrayList<ResidueTerm> tab_res_term){
		//TODO mettre un truc du genre if !und.isEmpty ou undParent : a voir
		boolean stop = false;
		for (int i=0; i<tab_res_term.size(); i++)
			if (undParent.contains(tab_res_term.get(i).getR().get(0)))
				stop = true;
			else
				stop = false;
		System.out.println("stop : " + stop);
		return stop;
	}


	public void format (ArrayList<String> r, ArrayList<String> l, String rep, String und){
		/*
		 * FORMAT THE GLYCANS (NEED BECAUSE OF REMOVING RESIDUES CHANGE NUMBERS), STOCK THE RESULTING GLYCAN IN THE STRING 'glycan'
		 */
		boolean rep_1 = false;
		if (changeInRep)
			rep_1 = true;
		Formatting f = new Formatting(r,l,rep, und, rep_1);
		outputSugar = f.format();
	}
	
	
	

	public String digestion(){
		createParts();
		
		System.out.println("res : " + res + "\n lin : " + lin + "\nenz : " + enz + "\n");
		boolean continuer = false; 
		ArrayList<String> r = res;
		ArrayList<String> l = lin;		
		ArrayList<Residue> tab_res = new ArrayList<Residue>();		
		ArrayList<ResidueTerm> tab_res_term = new ArrayList<ResidueTerm>();		
		Hashtable<String, Integer> term = new Hashtable<String,Integer>();	

		do {
			if (oneResidueFromString(inputSugar, 1)==1)
				break;
			continuer=false;
			clearArray (tab_res, tab_res_term, term);
			if (section.get("UND") == 1 && !und.isEmpty())
				underdeterminedTreatment();
			createTabResTerm(r, l, tab_res, tab_res_term, term);
			if (!tab_res_term.isEmpty()) 		
				removeResAndLink(l, r, tab_res, tab_res_term);
				
			if (section.get("REP") == 1 && !rep.isEmpty() && tab_res_term.isEmpty())
				continuer = repetitionTreatment(r,l,term);

		}
		while(!tab_res_term.isEmpty() && !stopLoop(tab_res_term) || continuer && !stopLoop(tab_res_term));
		
		format (r,l, rep, und);
		
		System.out.println("sugar DIGESTION : " + outputSugar + "##enz : " + enz + "\n");
		return outputSugar;
	}



	public void underdeterminedTreatment(){
		SectionUnd sectUnd = new SectionUnd(inputSugar, dico, enz, section, und, unkLink);
		undParent = sectUnd.treatUnd();
		und = sectUnd.getUnd();
	}

	public boolean repetitionTreatment (ArrayList<String> r, ArrayList<String> l, Hashtable<String, Integer> term){	
		SectionRep rs = new SectionRep(inputSugar, dico, enz, section, rep, unkLink);
		boolean cont = rs.treatTerminalRep(term, r, l);
		changeInRep = rs.isChangeInRep();
		r = rs.getRmain();
		l = rs.getLmain();
		rep = rs.getRep();
		return cont;
	}





}
