#ifndef IDEAL_CPP_HEADER
#define IDEAL_CPP_HEADER
#include <vector>
#include "Poly.h"
#include "kernel/ideals.h"
//base for ideals as well for modules
//doesn't need a destructor, as Polys will destroy itself
template <class poly_type> class IdealBase
{
 protected:
  std::vector<poly_type> storage;
 public:
  typedef poly_type value_type;
  typedef typename std::vector<poly_type>::size_type size_type;
  typedef typename std::vector<poly_type>::iterator iterator;
  typedef typename std::vector<poly_type>::difference_type difference_type;
  typedef typename std::vector<poly_type>::allocator_type allocator_type;
 IdealBase(){}

 IdealBase(iterator first,
             iterator last,
             const typename
             std::vector<poly_type>::allocator_type& __a = allocator_type()):
   storage(first,last,__a)
   {}
 ring getRing() const
 {
  //FIXME: is a hack
  if (size()>0)
  {
    return storage[0].getRing();
  }
  else
    return (ring) NULL;
 }
 poly_type& operator[] (int n)
 {
   return storage[n];
 }
 const poly_type& operator[](int n) const
 {
   return storage[n];
 }
 void push_back(const poly_type& p)
 {
   storage.push_back(p);
 }
 void push_front(const poly_type& p)
 {
   storage.push_front(p);
 }

 iterator begin()
 {
   return storage.begin();
 }
 iterator end()
 {
   return storage.end();
 }
 size_type size() const
 {
   return storage.size();
 }
 iterator
   insert(iterator __position, const value_type& __x)
   {
     return storage.insert(__position,__x);
   }
 iterator
   erase(iterator __position)
   {
     return storage.erase(__position);
   }
 iterator
   erase(iterator __first, iterator __last)
   {
     return storage.erase(__first,__last);
   }
 void insert(iterator __pos, iterator __first, iterator __last)
 {
   return insert(__pos,__first,__last);
 }
};

class Ideal:
public IdealBase<Poly>
{
 public:
  Ideal(){}
  Ideal(ideal i, ring r)
  {
    for(int j=0;j<IDELEMS(i);j++)
    {
      storage.push_back(Poly(i->m[j],r));
    }
  }
  Ideal(iterator first,
        iterator last,
        const allocator_type& __a = allocator_type()):
    IdealBase<Poly>(first,last,__a){}
 ideal as_ideal() const
 {
   //no checks for rings
   int s=size();

   if (s==0) s=1;

   ideal result=idInit(s,1);
   result->m[0]=NULL;
   s=size();
   for(int i=0;i<s;i++)
   {
     result->m[i]=storage[i].as_poly();
   }
   return result;
 }
};
class Module:
public IdealBase<Vector>
{
public:
 Module(ideal i, ring r)
 {
    for(int j=0;j<IDELEMS(i);j++)
    {
      storage.push_back(Vector(i->m[j],r));
    }
  }
  ideal as_module() const
  {
   //no checks for rings
        int s=size();

        if (s==0)
        s=1;

        ideal result=idInit(s,1);
        result->m[0]=NULL;
        s=size();
        for(int i=0;i<s;i++)
	{
            result->m[i]=storage[i].as_poly();
        }
    if (size()==0)
            result->rank=0;
        else
            result->rank=id_RankFreeModule(result,storage[0].getRing());
   return result;
  }
  Module(iterator first,
        iterator last,
        const allocator_type& __a = allocator_type()):
    IdealBase<Vector>(first,last,__a)
  {}
  Module()
  {}
};
#endif
