package mechanique;

 

/*    
    
    MechaniQue, the programming language for Interactive Fiction
    Copyright (C) 2007  G.J.G.T. (Gabor) de Mooij

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation (highest version applies !!).

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    ---MECHANIQUESOFT/GABOR DE MOOIJ

*/
 
import java.io.*;
import java.util.*;
import java.util.regex.*;
import java.applet.*;
import java.io.Serializable;
import java.lang.Math;
;

public class StoryFactory 
{

    public String[] lines;
    public ArrayList<String> locks = new ArrayList<String>();
    public String actionPart;
    public String[] actions;
    public String action;
    public String parameter;
    public Matcher m;
    public ActionFactory actionFactory;
    public LockFactory lockFactory; 
    public StoryInterface story;
    public int curLin;
    private Commandline cl = new Terminal();
   
    public StoryFactory(Commandline terminal)
    {
    	cl = terminal;
    	actionFactory = new ActionFactory(cl);
    	lockFactory = new LockFactory();
    }
  
    public int getCurrentLine()
    {
        return this.curLin;
    }
    
    public StoryInterface getStory()
    {
        return this.story;
    }
    
    public String simpleCleanup(String t)
    {
    	 	
    	
    		Pattern p = Pattern.compile("\\^(\\+|\\-)\\w+\\*(\\-|\\+)\\s*?\\w+");//(\\+|\\-)");
    		Matcher m = p.matcher(t);
    		if (m.find()){
              cl.print("signed quantifiers not allowed:"+m.group(0));
              System.exit(0);
    		}
        
    		//comfort function, transforms a line like @&outside in: @[outside]^&|^:Outside. 
    		 p = Pattern.compile("@&([^\\n\\r@]+)");
             m = p.matcher(t);
             while (m.find()){
                 String item = m.group(1);
                 String rplc = "@["+item+"]^&|^:"+toolbox.ucfirst(item)+".";
                 //System.out.println("DEBUG:"+m.group(0)+" replaced for "+rplc+"("+n1+","+n2+","+item+")");
                 t = t.replace(m.group(0),rplc);
             }
             
    		/*
    		p = Pattern.compile("@&([^\\n\\r@]+)");
    	 	m = p.matcher(t);
    	 	while (m.find()){
    	 		t = t.replace("@&"+m.group(1),"@["+m.group(1)+"]^&|^:"+toolbox.ucfirst(m.group(1))+".");
    	 	}
    		*/
             
    	 	//System.out.print(t);
    		
            p = Pattern.compile("@\\[(\\S+?)\\]fin");
            m = p.matcher(t);
            if (m.find()){
                t = t.replace("@["+m.group(1)+"]fin","@["+m.group(1)+"]^#\\n@fin");
            }
            
            p = Pattern.compile("\\{=(.*?)\\*(\\d+)\\}");
            m = p.matcher(t);
            while (m.find()){
                String item = m.group(1);
                String n1 = m.group(2);
                String n2 = (new Integer((new Integer(n1))+1)).toString();
                String rplc = "{!"+item+"*"+n2+"}{"+item+"*"+n1+"}";
                //System.out.println("DEBUG:"+m.group(0)+" replaced for "+rplc+"("+n1+","+n2+","+item+")");
                t = t.replace(m.group(0),rplc);
            }
            
            p = Pattern.compile("\\{!=(.*?)\\*(\\d+)\\}");
            m = p.matcher(t);
            while (m.find()){
                String item = m.group(1);
                String n1 = m.group(2);
                String n2 = (new Integer((new Integer(n1))+1)).toString();
                String rplc = "{"+item+"*"+n2+"}{!"+item+"*"+n1+"}{OR}";
                //System.out.println("DEBUG:"+m.group(0)+" replaced for "+rplc+"("+n1+","+n2+","+item+")");
                t = t.replace(m.group(0),rplc);
            }
            
            t = t.replaceAll("\\{;","{_DESCRIBE_FULL");
            t = t.replaceAll("\\{!;","{!_DESCRIBE_FULL");
            
                
                
            return t;
    }
    
    
    public StoryInterface make(String t)
    {
        
        //First we do some clean-up..
        t = this.simpleCleanup(t);
        
        //configure the LockFactory
        lockFactory.setParent(this);
        
        //First, split the string into lines
        this.lines = t.split("@");
        
        //Create an empty story object
        this.story = new Story();
        
        
        
        for (int j=0; j<this.lines.length; j++)
        {
            this.curLin = j;
            //Create a new storyline
            StoryLineInterface storyLine = new StoryLine();
            
            //Add the storyline to the story
            this.story.add(storyLine);
            
            //now break the line into parts
            Pattern p = Pattern.compile("^(\\[\\S+?\\])?(\\{.*\\})?(<<|>>)?(.*)$");
            Matcher m = p.matcher(this.lines[j]);
            
            String lineContent =  this.lines[j];
            int lineNumber = j;
       
            if (m.find()){
                
                
                
                if (m.group(1)!=null)
                {
                   String lbl = m.group(1); 
                   this.story.setLabel(lbl.replace("[","").replace("]",""),j);
                }
                
                if (m.group(2)!=null)
                {
                    //add locks
                    String lck = m.group(2).replace("}{","}|{");
                    String[] ps = lck.split("\\|");
                    for (int i=0; i<ps.length; i++)
                    {
                        storyLine.addLock(this.lockFactory.make(ps[i]));
                    }
                }
                
                if (m.group(3)!=null)
                {
                    //add extended lock
                    storyLine.addLock(this.lockFactory.make(m.group(3)));
                    
                }
                
                if (m.group(4)!=null)
                {
                    //add actions
                    String a = m.group(4);
                    String[] ac = a.split("\\|");
                    for (int i=0; i<ac.length; i++)
                    {
                        if (ac[i].indexOf("^")==0) storyLine.addAction(this.actionFactory.make(ac[i]));
                    }
                }
                
                
            } else {
                if (!lineContent.startsWith("fin")){
                
                    cl.print("SYNTAX ERROR IN: "+lineNumber);
                    cl.print("("+lineContent+")");
                    //System.exit(0);
                
                }
            }
        
            
        }
        
        return this.story;
        
    }
}
