#include "Fastor/Fastor.h"
#include "Fastor/tensor/AbstractTensorFunctions.h"

namespace f = Fastor;
using dtype = double;

template<unsigned maxBondDim, unsigned localDim>
class MPS {
    using BTensor_t = f::Tensor<dtype, maxBondDim, localDim, maxBondDim>;
    public:
        MPS(std::vector<f::Tensor<dtype>>&& Bs, std::vector<f::Tensor<dtype>>&& Ss) {
            assert(Bs.size() == Ss.size());
            this->Bs = std::move(Bs);
            this->Ss = std::move(Ss);
            this->L = Bs.size();
        }
    private:
        std::vector<f::Tensor<dtype>> Bs;
        std::vector<f::Tensor<dtype>> Ss;
        unsigned L;
};

// class TensorContainer {
//     public:
//         TensorContainer(Tensor t);

// };


int main() {
    // std::vector<f::Tensor<dtype, 2, 2, 1>> Bs = {
    //     // f::Tensor<dtype, 1, 2, 1>({{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}}),
    //     // f::Tensor<dtype, 1, 2, 1>({{{1, 2}}}),
    //     f::Tensor<dtype, 1, 2, 1>({{{1}, {2}}}),
    //     // f::Tensor<dtype, 1, 10, 1>({{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}}),
    // };
    f::Tensor<dtype, 10, 2, 10> t1;
    t1.zeros();
    std::cout << t1 << std::endl;
    t1(0,1,0) = .69;
    std::cout << t1 << std::endl;

    f::Tensor<dtype, 10, 2, 10> t2;
    t2.ones();

    std::vector<f::Tensor<dtype, 10, 2, 10>> Bs = { t1, t2 };

    //({{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}});
    // auto t2 = f::Tensor<dtype, 1, 10, 1>({{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}});

    // f::Tensor<dtype, 1, 5, 1>
    // for (auto& b : Bs) {
    //     std::cout << b << std::endl;
    // }

    // f::Tensor<dtype, 1, 2, 1> t1View = t1(f::seq(0, 1), f::all, f::seq(0, 1));
    auto t1View = t1(f::seq(0, 10), f::all, f::seq(0, 10));
    auto t2View = t2(f::seq(0, 10), f::all, f::seq(0, 10));
    // auto t1View = t1(f::seq(0, 1), f::all, f::seq(0, 1));
    // std::cout << t1View.dimension(0) << std::endl;
    // std::cout << t1View.dimension(1) << std::endl;
    // std::cout << t1View.dimension(2) << std::endl;
    // std::cout << t1View << std::endl;
    f::Tensor<dtype, 1> t3 = f::evaluate(f::einsum<f::Index<0, 1, 2>, f::Index<0, 1, 2>>(t1View, t2View));
    // f::Tensor<dtype, 1> t3 = f::einsum<f::Index<0, 1, 2>, f::Index<0, 1, 2>>(t1, t2);
    std::cout << t3.dimension(0) << std::endl;
    std::cout << t3(0) << std::endl;

    return 0;
}
