/* Copyright (c) 1997-2011
   Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Darmstadt, Germany)
   http://www.polymake.de

   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; either version 2, or (at your option) any
   later version: http://www.gnu.org/licenses/gpl.txt.

   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.
--------------------------------------------------------------------------------
   $Project: polymake $$Id: permlib.h 10289 2011-06-09 16:02:25Z herr $
*/

#ifndef POLYMAKE_GROUP_H
#define POLYMAKE_GROUP_H
#undef DOMAIN
#include "polymake/Array.h"
#include "polymake/Set.h"
#include "permlib/permlib_api.h"
#include <list>

namespace polymake{ namespace group{

    enum Domain{
      OnFacets, OnRays, OnCoords
    };

 
class PermlibGroup {
protected:
  boost::shared_ptr<permlib::PermutationGroup> permlib_group;
  
public:
  PermlibGroup(){};
  PermlibGroup(const Array< Array < int> >& generators){
    std::list<boost::shared_ptr<permlib::Permutation> > permutations;
    for(Entire< Array< Array <int> > >::const_iterator perm = entire(generators); !perm.at_end(); ++perm){
      boost::shared_ptr<permlib::Permutation> gen(new permlib::Permutation((*perm).begin(),(*perm).end()));
      permutations.push_back(gen);
    }
    permlib_group = construct(generators[0].size(), permutations.begin(), permutations.end());
  }

  boost::shared_ptr<permlib::PermutationGroup> get_permlib_group() const{
    return permlib_group;
  }

  Array< Array<int> > strong_gens() const {
    Array< Array<int> > permutations(permlib_group->S.size());
    int count=0;
    for(std::list<boost::shared_ptr<permlib::Permutation> >::const_iterator perm = permlib_group->S.begin(); perm!=permlib_group->S.end(); ++perm){
      permutations[count]=perm2Array(*perm);
      ++count;
    }    
  return permutations;
  }

  Array<int> base() const {
    return Array<int>(permlib_group->B.size(),entire(permlib_group->B));
  }

  Array< Array < Array<int> > > transversals() const {
    int base_length=permlib_group->B.size();
    Array< Array < Array<int> > > trans(base_length);
    for (int i=0; i<base_length; ++i) {
      Array < Array<int> > single_trans(permlib_group->n);
      for (unsigned int j=0; j<permlib_group->n; ++j) {
        boost::shared_ptr<permlib::Permutation> perm(permlib_group->U[i].at(j));
        single_trans[j]=perm2Array(perm);
      }
      trans[i]=single_trans;
    }
    return trans;
  }


  Array<int> perm2Array(const boost::shared_ptr<permlib::Permutation> perm) const{
    if(!perm){
      return Array<int>();
    } else {
      Array<int> gen(perm->size());
      for (unsigned int i=0; i<perm->size(); i++) {
        gen[i]=perm->at(i);
      }
      return gen;
    }
  }

};

  //template<typename Domain>
class PermlibGroupOfCone : public PermlibGroup{
public:
  PermlibGroupOfCone(){};
  PermlibGroupOfCone(const Array< Array < int> >& generators) : PermlibGroup(generators){  }

  Array< Set<int> > orbits() const{

    std::list<boost::shared_ptr<permlib::OrbitAsSet> > orbit_list = permlib::orbits(*permlib_group);

    Array< Set<int> > orbit_decomp(orbit_list.size());
    int count=0;
    for(std::list<boost::shared_ptr<permlib::OrbitAsSet> >::const_iterator orbit = orbit_list.begin(); orbit!=orbit_list.end(); ++orbit){
      Set<int> orbit_set;
      for(permlib::OrbitAsSet::const_iterator orb_it = (*orbit)->begin();orb_it!=(*orbit)->end();++orb_it){
        unsigned long elem=*orb_it;
        orbit_set+=static_cast<int>(elem);
      }
      orbit_decomp[count]=orbit_set;
      count++;
    }
    return orbit_decomp;
  }

};


 } // end namespace group
} // end namespace polymake

#endif // POLYMAKE_GROUP_H

// Local Variables:
// mode:C++
// c-basis-offset:3
// indent-tabs-mode:nil
// End:
