#pragma once

#ifndef STATIC_VECTOR_H_1AD74FC6AD524c8aB61ABB4C3E75C1AF
#define STATIC_VECTOR_H_1AD74FC6AD524c8aB61ABB4C3E75C1AF

#include <new>
#include <iterator>
#include <utility>

#include <util/generic/noncopyable.h>

namespace NWebmaster {

template <typename t_data_type, size_t t_capacity>
class const_size_vector : public TNonCopyable {
public:
    typedef const_size_vector<t_data_type, t_capacity> this_type;
    typedef std::random_access_iterator_tag iterator_category;
    typedef t_data_type value_type;
    typedef size_t difference_type;
    typedef t_data_type *pointer;
    typedef const t_data_type *const_pointer;
    typedef t_data_type &reference;
    typedef const t_data_type &const_reference;
    typedef pointer iterator;
    typedef const_pointer const_iterator;

    inline const_size_vector() :
        vec(new char[t_capacity *sizeof(value_type)]),
        end_val(vec),
        cnt(0) {
    }

    inline ~const_size_vector() {
        clear();
        delete[] reinterpret_cast<char *>(vec);
    }

    template <typename t_type>
    inline void push_back(const t_type &value) {
        new(end_val) value_type(value);
        ++cnt;
        end_val += sizeof(value_type);
    }

    inline const_reference operator[](size_t idx) const    {
        return reinterpret_cast<const_reference>(vec[idx * sizeof(value_type)]);
    }
    inline reference operator[](size_t idx)                {
        return reinterpret_cast<reference>(vec[idx * sizeof(value_type)]);
    }

    inline const_iterator begin() const                    {
        return reinterpret_cast<const_iterator>(vec);
    }
    inline iterator begin()                                {
        return reinterpret_cast<iterator>(vec);
    }

    inline const_iterator end() const                      {
        return reinterpret_cast<const_iterator>(end_val);
    }
    inline iterator end()                                  {
        return reinterpret_cast<iterator>(end_val);
    }

    inline void clear() {
        for (reference val : *this) {
            val.~value_type();
            operator delete(&val, &val);
        }
        cnt = 0;
        end_val = vec;
    }

    inline size_t size() const {
        return cnt;
    }
    inline bool empty() const  {
        return (0 == cnt);
    }

    inline void swap(this_type &cont) {
        using std::swap;
        swap(vec, cont.vec);
        swap(end_val, cont.end_val);
        swap(cnt, cont.cnt);
    }

private:
    char *vec;
    char *end_val;
    size_t cnt;
};

} //namespace

#endif
