#ifndef COLLECTION_HPP
#define COLLECTION_HPP

#include "symbol.hpp"
#include <deque>

class collection : public symbol_impl_proxy<collection> {
    using base = std::deque<symbol>;

    base vals;

public :
    using iterator = base::iterator;
    using const_iterator = base::const_iterator;
    using reverse_iterator = base::reverse_iterator;
    using const_reverse_iterator = base::const_reverse_iterator;

    collection();

    void push_back(symbol&& s);
    void push_front(symbol&& s);
    symbol pop_back();
    symbol pop_front();
    std::size_t size() const;
    bool empty() const;

    symbol& operator [] (std::size_t i);
    const symbol& operator [] (std::size_t i) const;

    template<typename T>
    T& as(std::size_t i) {
        return vals[i].as<T>();
    }

    template<typename T>
    const T& as(std::size_t i) const {
        return vals[i].as<T>();
    }

    iterator begin();
    const_iterator begin() const;
    reverse_iterator rbegin();
    const_reverse_iterator rbegin() const;

    iterator end();
    const_iterator end() const;
    reverse_iterator rend();
    const_reverse_iterator rend() const;

    collection* clone() const override;
    collection* evaluate(const interpreter_context& context) const override;
    std::string serialize(const interpreter_context& context) const override;
    static const std::string& static_type_name();
    bool is_litteral() const override;
    std::pair<std::size_t,std::size_t> priority(const interpreter_context&) const override;

    static void reg(interpreter_context& context);
};

#endif
