// Copyright (C) 1996 DIMACS Center, Rutgers, The State University of New Jersey
// Author(s): Jonathan Berry

// This software is copyrighted by the DIMACS Center at Rutgers, The State
// University of New Jersey.  IT IS PROVIDED AS IS, AND THE AUTHORS, DIMACS, AND
// RUTGERS, THE STATE UNIVERSITY OF NEW JERSEY  DISCLAIM
// ALL LIABILITY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
// DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

// THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE
// IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
// NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
// MODIFICATIONS.

// The authors hereby grant permission to use, copy, modify, distribute,
// and license this software and its documentation for any purpose, provided
// that existing copyright notices are retained in all copies and that this
// notice is included verbatim in any distributions. No written agreement,
// license, or royalty fee is required for any of the authorized uses.
// Modifications to this software may be copyrighted by their authors
// and need not follow the licensing terms described here, provided that
// the new terms are clearly indicated on the first page of each file where
// they apply.

// Last File Update: 31-Jul-1996
// 

#ifndef Sequence_h
#define Sequence_h

#include <LINK/basic/Permutation.h>
#include <LINK/basic/Set.h>

#ifndef DEFAULT_SEQ_IMPL
#define DEFAULT_SEQ_IMPL  List
#endif


template <class Item, class Impl> 
class SequenceBase : public MSetBase<Item, Impl> {
public:
    SequenceBase();
    SequenceBase(const SequenceBase<Item, Impl>& s);
    SequenceBase(const Collection<Item>& c);
    SequenceBase(const Container<Item>& c);

    SequenceBase<Item,Impl>&	operator=(const SequenceBase<Item,Impl>& c);  
    //SequenceBase<Item,Impl>& 	copy(const SequenceBase<Item,Impl>& c) 
    //					{*this = c; return *this; 	}
    SequenceBase<Item,Impl>&	operator=(const Collection<Item>&c);
    DataType		type() const    { return SEQCOL;  		}

    void		insert(Item e) { newSequence(this); store->insert(e);  }
    void		prepend(Item e){ newSequence(this); store->prepend(e); }
    void		append(Item e) { newSequence(this); store->append(e);  }
    void		insertAfter(Item e, Item after_item);
    void		insertBefore(Item e, Item before_item);

    //MSetBase<Item,DEFAULT_SET_IMPL<Item> > unions(Collection<Item>& c);
    //MSetBase<Item,DEFAULT_SET_IMPL<Item> > operator+(Collection<Item>& c);
    //MSetBase<Item,DEFAULT_SET_IMPL<Item> > intersection(Collection<Item>& c);
    //MSetBase<Item,DEFAULT_SET_IMPL<Item> > operator^(Collection<Item>& c);
    //MSetBase<Item,DEFAULT_SET_IMPL<Item> > difference(Collection<Item>& c);
    //MSetBase<Item,DEFAULT_SET_IMPL<Item> > operator-(Collection<Item>& c);



    ostream&		display(ostream& os) const;
    
    //void		reverse();
    //void		swap(Item e1, Item e2);
    //SequenceBase	positions(Item e);  // return type seq<int>

    Item                      element (int i);
    SequenceBase<Item,Impl>   subsequence(int i, int j);
    int                       search(SequenceBase<Item,Impl>* str);
    Bool                      SBmemberQ(SequenceBase<Item,Impl>* str) 
                                { return (search(str)==-1 ? FALSE : TRUE); }
    Collection<Item>*   newEmpty() const 
				{return new SequenceBase<Item,Impl>; }

    //SequenceBase<Item,Impl>& insert(Item char, int pos)
    //SequenceBase<Item,Impl>& insert(SequenceBase<Item> str, int pos)

    //SequenceBase<Item,Impl>& replace(Item char, int pos)
    //SequenceBase<Item,Impl>& replace(SequenceBase<Item> str, int pos)

    //SequenceBase<Item,Impl>& remove(int i);
    //SequenceBase<Item,Impl>& remove(int i, int j);

    //SequenceBase<Item,Impl>& operator+(SequenceBase<Item,Impl>& str) 
    //                        { return union(str); }
    //SequenceBase<Item,Impl>& union(SequenceBase<Item,Impl>& str);


protected:
    void		newSequence(SequenceBase<Item,Impl>* s);
    void		newStore();
    //friend class CollectionWrapper<Item>;
};


template <class Item> 
class Sequence : public SequenceBase<Item, DEFAULT_SEQ_IMPL<Item> > {
public:
    Sequence() {}
    Sequence(const Sequence<Item>& s) :
			SequenceBase<Item, DEFAULT_SEQ_IMPL<Item> >(s) {}
    Sequence(const Collection<Item>& c) :
			SequenceBase<Item, DEFAULT_SEQ_IMPL<Item> >(c) {}
    Sequence(const Container<Item>& c) :
			SequenceBase<Item, DEFAULT_SEQ_IMPL<Item> >(c) {}

    Sequence<Item>&	operator=(const Sequence<Item>& s);
    Sequence<Item>&	operator=(const Collection<Item>& c);
    //friend class CollectionWrapper<Item>;
};

#define SEQUENCE(etype, itype)	SequenceBase<etype, itype<etype> >

#ifdef DEFINE_TEMPLATE
#include <LINK/basic/Sequence.cc>
#endif


#endif
