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;

   }
}