#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 "termorder.h"
#include "ep_standard.h"
#include "ep_xfig.h"
#include "gfanapplication.h"
#include "symmetry.h"

class PolynomialSetUnionApplication : public GFanApplication
{
  SimpleOption optionSpecialMode;
  FieldOption theFieldOption;
  class PolynomialCmp
  {
  public:
    bool operator()(const Polynomial &a, const Polynomial &b)const
    {
      if(a.getMarked().m.exponent.sum()<b.getMarked().m.exponent.sum())return true;
      if(a.getMarked().m.exponent.sum()>b.getMarked().m.exponent.sum())return false;
      return LexicographicTermOrder()(a.getMarked().m.exponent,b.getMarked().m.exponent);
    }
  };
public:
  const char *helpText()
  {
    return "This program computes the union of a list of polynomial sets given as input.\n";
  }
  PolynomialSetUnionApplication():
    optionSpecialMode("-s","Sort output by degree.\n")
  {
    registerOptions();
  }
  char *name()
  {
    return "_polynomialsetunion";
  }
  int main()
  {
    /*      SymmetryGroup g(16);
      //      g.computeClosure(StringParser("(1,2,3,0,5,6,7,4,9,10,11,8,13,14,15,12)").parseIntegerVector());
      //      g.computeClosure(StringParser("(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)").parseIntegerVector());
      g.computeClosure(StringParser("(1,0,2,3,5,4,6,7,9,8,10,11,13,12,14,15)").parseIntegerVector());
      g.computeClosure(StringParser("(0,2,1,3,4,6,5,7,8,10,9,11,12,14,13,15)").parseIntegerVector());
      g.computeClosure(StringParser("(0,1,3,2,4,5,7,6,8,9,11,10,12,13,15,14)").parseIntegerVector());
      g.computeClosure(StringParser("(0,2,1,3,4,6,5,7,8,10,9,11,12,14,13,15)").parseIntegerVector());
      
      g.computeClosure(StringParser("(4,5,6,7,0,1,2,3,8,9,10,11,12,13,14,15)").parseIntegerVector());
      g.computeClosure(StringParser("(8,9,10,11,4,5,6,7,0,1,2,3,12,13,14,15)").parseIntegerVector());
      g.computeClosure(StringParser("(12,13,14,15,4,5,6,7,8,9,10,11,0,1,2,3)").parseIntegerVector());
      g.computeClosure(StringParser("(8,9,10,11,4,5,6,7,0,1,2,3,12,13,14,15)").parseIntegerVector());

      g.print(Stderr);
*/

    FileParser P(Stdin);
    PolynomialSet s;
    int c=P.nextNonBlank();
    bool first=true;
    assert(P.isLeftBrackets(c));
    while(','==c || first)
      {
	static int t;
	if(!((t++)&255))fprintf(Stderr,"%i\n",t-1);
	PolynomialSet temp=P.parsePolynomialSet();
	//	if(optionSpecialMode.getValue())temp.markAndScale(LexicographicTermOrder());
	s.unionSet(temp);
	c=P.nextNonBlank();
	first=false;
      }
    assert(P.isRightBrackets(c));

    PolynomialSet S;

    for(PolynomialSet::const_iterator i=s.begin();i!=s.end();i++)
      {
	S.unionPolynomial((*i));
	//	S.unionPolynomial(g.computeUniqueRepresentative(*i));
      }
    

    if(optionSpecialMode.getValue())S.sort(PolynomialCmp());

    AsciiPrinter(Stdout).printPolynomialSet(S);
    /*
    PolynomialSet total;
    for(PolynomialSet::const_iterator i=S.begin();i!=S.end();i++)
      {
	AsciiPrinter(Stdout).printPolynomial(*i);
	PolynomialSet a;
	for(SymmetryGroup::ElementContainer::const_iterator j=g.elements.begin();j!=g.elements.end();j++)
	  {
	    a.unionPolynomial(g.permutePolynomial(*i,*j));
	    total.unionPolynomial(g.permutePolynomial(*i,*j));
	  }
	fprintf(Stdout,"\nelments in class: %i\n",a.size());
	fprintf(Stdout,"Total so far: %i\n\n",total.size());
      }
    */
    return 0;
  }
};

static PolynomialSetUnionApplication theApplication;
