#include "parser.h"
#include "printer.h"
#include "polynomial.h"
#include "division.h"
#include "buchberger.h"
#include "wallideal.h"
#include "lp.h"
#include "reversesearch.h"
#include "polyhedralfan.h"
#include "breadthfirstsearch.h"
#include "termorder.h"
#include "ep_standard.h"
#include "ep_xfig.h"
#include "gfanapplication.h"
#include "timer.h"
#include "polyhedralfan.h"

class IsRefinementApplication : public GFanApplication
{
  FieldOption theFieldOption;
  SimpleOption restrictedOption;
public:
  bool includeInDefaultInstallation()
  {
    return false;
  }
  const char *helpText()
  {
    return "This program .\n";
  }
  IsRefinementApplication():
    restrictedOption("--restricted","help")
  {
    registerOptions();
  }    

  char *name()
  {
    return "_isrefinement";
  }

  void printVectorList(IntegerVectorList const &l)
  {
    fprintf(Stdout,"<IntegerVectorList>");
    for(IntegerVectorList::const_iterator i=l.begin();i!=l.end();i++)
      {
	fprintf(Stdout,"<IntegerVector>");
	AsciiPrinter(Stdout).printVector(*i);
	fprintf(Stdout,"</IntegerVector>");
      }
    fprintf(Stdout,"</IntegerVectorList>");
  }

  int main()
  {
    Field::printList(Stderr);

    LpSolver::printList(Stderr);
    lpSetSolver("cddgmp");
     
    FileParser p(Stdin);

    PolynomialSetList a=p.parsePolynomialSetList();
    PolynomialSetList b=p.parsePolynomialSetList();

    int dimA=a.begin()->numberOfVariablesInRing();
    int dimB=b.begin()->numberOfVariablesInRing();

    int dim=dimA;
    if(dimB<dimA)dim=dimB;

    if(0)
      {
    PolyhedralFan A(dim);
    for(PolynomialSetList::const_iterator i=a.begin();i!=a.end();i++)
      {
	PolyhedralCone C=groebnerCone(*i);
	if(dimA>dimB)
	  C=C.withLastCoordinateRemoved();
	//C=intersection(C,PolyhedralCone::positiveOrthant(dim));
	C.canonicalize();
	A.insert(C);
      }    
    PolyhedralFan B(dim);
    for(PolynomialSetList::const_iterator i=b.begin();i!=b.end();i++)
      {
	PolyhedralCone C=groebnerCone(*i);
	if(dimB>dimA)
	  C=C.withLastCoordinateRemoved();
	//C=intersection(C,PolyhedralCone::positiveOrthant(dim));
	C.canonicalize();
	B.insert(C);
      }    

    fprintf(Stdout,"%i\n",A.isRefinementOf(B));
      }
    else
      {
	list<PolyhedralCone> al;
	for(PolynomialSetList::const_iterator j=a.begin();j!=a.end();j++)
	  {
	    PolyhedralCone C2=groebnerCone(*j);
	    C2.canonicalize();
	    C2=C2.withLastCoordinateRemoved();
	    if(restrictedOption.getValue())
	      {
		C2=intersection(C2,PolyhedralCone::positiveOrthant(C2.ambientDimension()));
		C2.canonicalize();
	      }
	    al.push_back(C2);
	  }
	AsciiPrinter P(Stdout);
	P.printString("<main>\n");
	for(PolynomialSetList::const_iterator i=b.begin();i!=b.end();i++)
	  {
	    static int t;
	    t++;
	    fprintf(Stderr,"%i\n",t);


	    P.printString("<cone>\n");
	    P.printString("<gbasis>\n");
	    P.printPolynomialSet(*i,true);
	    P.printString("</gbasis>\n");

	    P.printString("<initialideal>\n");
	    P.printPolynomialSet(i->markedTermIdeal(),true);
	    P.printString("</initialideal>\n");

	    P.printString("<facets>\n");
	    PolyhedralCone C=groebnerCone(*i);
	    C.canonicalize();
	    if(restrictedOption.getValue())
	      {
		C=intersection(C,PolyhedralCone::positiveOrthant(C.ambientDimension()));
		C.canonicalize();
	      }
	    printVectorList(C.getHalfSpaces());
	    P.printString("</facets>\n");
	    P.printString("<interiorpoint>\n");
	    P.printVector(C.getRelativeInteriorPoint());
	    P.printString("</interiorpoint>\n");


	    P.printString("<subdivision>\n");
	    list<PolyhedralCone>::const_iterator j2=al.begin();
	    for(PolynomialSetList::const_iterator j=a.begin();j!=a.end();j++)
	      {
		//		PolyhedralCone C2=groebnerCone(*j);
		//	C2.canonicalize();
		//	C2=C2.withLastCoordinateRemoved();
		PolyhedralCone C2=*j2;
		PolyhedralCone c=intersection(C,C2);
		if(c.dimension()==C.dimension())
		  {
		    if(C.contains(C2))
		      {
			P.printString("<cone>\n");
			P.printString("<gbasis>\n");
			P.printPolynomialSet(*j,true);
			P.printString("</gbasis>\n");
			P.printString("<initialideal>\n");
			P.printPolynomialSet(j->markedTermIdeal(),true);
			P.printString("</initialideal>\n");
			P.printString("<facets>\n");
			printVectorList(C2.getHalfSpaces());
			P.printString("</facets>\n");
			P.printString("<interiorpoint>\n");
			P.printVector(C2.getRelativeInteriorPoint());
			P.printString("</interiorpoint>\n");
			P.printString("</cone>\n");		    
		      }
		  }
		j2++;
	      }
	    P.printString("</subdivision>\n");

	    P.printString("</cone>\n");
	  }
	P.printString("</main>\n");
      }
    
    return 0;
  }
};

static IsRefinementApplication theApplication;

