// Copyright (C) 2026 Kiyotsugu Arai
// SPDX-License-Identifier: LGPL-3.0-or-later

// vector_base.hpp
//
// ベクトル基本クラスの定義
//
// このファイルでは、MKL代数ライブラリのベクトルクラスの基底クラスを定義します。
// このクラスは、異なるストレージ戦略を持つベクトルクラスに共通の機能を提供します。
//
// 主な機能:
// - 共通のベクトルインターフェース
// - ストレージに依存しない操作
// - イテレータとアクセサ

#ifndef CALX_VECTOR_BASE_HPP
#define CALX_VECTOR_BASE_HPP

#include "vector_storage.hpp"
#include "../common.hpp"
#include <math/concepts/algebraic_concepts.hpp>
#include <math/core/traits.hpp>

#include <cstddef>
#include <initializer_list>
#include <type_traits>

namespace calx {
namespace detail {

//-----------------------------------------------------------------------------
// ベクトル基本クラス
//-----------------------------------------------------------------------------

template<typename T, typename StoragePolicy>
    requires concepts::AdditiveGroup<T>  // 加法群の要件を追加
class VectorBase {
public:
    using value_type = T;
    using size_type = std::size_t;
    using difference_type = std::ptrdiff_t;
    using reference = T&;
    using const_reference = const T&;
    using pointer = T*;
    using const_pointer = const T*;
    using iterator = typename StoragePolicy::iterator;
    using const_iterator = typename StoragePolicy::const_iterator;
    
    // デフォルトコンストラクタ（ストレージポリシーに依存）
    VectorBase() = default;
    
    // サイズ指定コンストラクタ
    explicit VectorBase(size_type size) : storage_(size) {}
    
    // サイズと初期値指定コンストラクタ
    VectorBase(size_type size, const T& value) : storage_(size, value) {}
    
    // イテレータ範囲コンストラクタ
    template<typename InputIt>
    VectorBase(InputIt first, InputIt last) : storage_(first, last) {}
    
    // 初期化リストコンストラクタ
    VectorBase(std::initializer_list<T> init) : storage_(init) {}
    
    // コピー/ムーブコンストラクタとコピー/ムーブ代入演算子（デフォルト）
    VectorBase(const VectorBase&) = default;
    VectorBase(VectorBase&&) noexcept = default;
    VectorBase& operator=(const VectorBase&) = default;
    VectorBase& operator=(VectorBase&&) noexcept = default;
    
    // デストラクタ
    ~VectorBase() = default;
    
    // 要素アクセス
    
    // 添字アクセス（非const）
    reference operator[](size_type pos) {
        return storage_[pos];
    }
    
    // 添字アクセス（const）
    const_reference operator[](size_type pos) const {
        return storage_[pos];
    }
    
    // 範囲チェック付き添字アクセス（非const）
    reference at(size_type pos) {
        return storage_.at(pos);
    }
    
    // 範囲チェック付き添字アクセス（const）
    const_reference at(size_type pos) const {
        return storage_.at(pos);
    }
    
    // 先頭要素アクセス（非const）
    reference front() {
        if (empty()) {
            throw IndexError("VectorBase::front: empty container");
        }
        return storage_.front();
    }
    
    // 先頭要素アクセス（const）
    const_reference front() const {
        if (empty()) {
            throw IndexError("VectorBase::front: empty container");
        }
        return storage_.front();
    }
    
    // 末尾要素アクセス（非const）
    reference back() {
        if (empty()) {
            throw IndexError("VectorBase::back: empty container");
        }
        return storage_.back();
    }
    
    // 末尾要素アクセス（const）
    const_reference back() const {
        if (empty()) {
            throw IndexError("VectorBase::back: empty container");
        }
        return storage_.back();
    }
    
    // データポインタアクセス（非const）
    T* data() noexcept {
        return storage_.data();
    }
    
    // データポインタアクセス（const）
    const T* data() const noexcept {
        return storage_.data();
    }
    
    // イテレータ
    
    // 先頭イテレータ（非const）
    iterator begin() noexcept {
        return storage_.begin();
    }
    
    // 先頭イテレータ（const）
    const_iterator begin() const noexcept {
        return storage_.begin();
    }
    
    // 先頭イテレータ（常にconst）
    const_iterator cbegin() const noexcept {
        return storage_.cbegin();
    }
    
    // 末尾イテレータ（非const）
    iterator end() noexcept {
        return storage_.end();
    }
    
    // 末尾イテレータ（const）
    const_iterator end() const noexcept {
        return storage_.end();
    }
    
    // 末尾イテレータ（常にconst）
    const_iterator cend() const noexcept {
        return storage_.cend();
    }
    
    // 容量
    
    // 空かどうかの確認
    bool empty() const noexcept {
        return storage_.empty();
    }
    
    // サイズの取得
    size_type size() const noexcept {
        return storage_.size();
    }
    
    // 全要素のスカラー値への設定
    void fill(const T& value) {
        std::fill(begin(), end(), value);
    }
    
    // ゼロクリア
    void zero() {
        fill(numeric_traits<T>::zero());
    }
    
    // ストレージの取得（実装の詳細）
    StoragePolicy& storage() noexcept {
        return storage_;
    }
    
    const StoragePolicy& storage() const noexcept {
        return storage_;
    }
    
protected:
    StoragePolicy storage_;
};

} // namespace detail
} // namespace calx

#endif // CALX_VECTOR_BASE_HPP