using NDTensors,
      Test

@testset "DenseTensor basic functionality" begin

  A = Tensor(3,4)

  for I in eachindex(A)
    @test A[I] == 0
  end

  randn!(A)

  for I in eachindex(A)
    @test A[I] != 0
  end

  for I in eachindex(A)
    @test A[I] != 0
  end

  @test ndims(A) == 2
  @test dims(A) == (3,4)
  @test inds(A) == (3,4)

  A[1,1] = 11

  @test A[1,1] == 11

  Aview = A[2:3,2:3]

  @test dims(Aview) == (2,2)
  @test A[2,2] == Aview[1,1]

  @test A * 2.0 == 2.0 * A

  Asim = similar(data(A), 10)
  @test eltype(Asim) == Float64
  @test length(Asim) == 10

  B = Tensor(undef,3,4)
  randn!(B)

  C = A+B

  for I in eachindex(C)
    @test C[I] == A[I] + B[I]
  end

  Ap = permutedims(A,(2,1))

  for I in eachindex(A)
    @test A[I] == Ap[NDTensors.permute(I,(2,1))]
  end

  t = Tensor(ComplexF64,100,100)
  randn!(t)
  @test conj(data(store(t))) == data(store(conj(t)))
  @test typeof(conj(t)) <: DenseTensor


  @test Dense(ComplexF64) == Dense{ComplexF64}()
  @test Dense(ComplexF64) == complex(Dense(Float64))

  D = Tensor(ComplexF64,(100,100))
  @test eltype(D) == ComplexF64
  @test ndims(D) == 2
  @test dim(D) == 100^2

  E = Tensor(ComplexF64,undef, (100,100))
  @test eltype(E) == ComplexF64
  @test ndims(E) == 2
  @test dim(E) == 100^2

  F = Tensor((100,100))
  @test eltype(F) == Float64
  @test ndims(F) == 2
  @test dim(F) == 100^2

  G = Tensor(undef, (100,100))
  @test eltype(G) == Float64
  @test ndims(G) == 2
  @test dim(G) == 100^2

  H = Tensor(ComplexF64,undef, 100,100)
  @test eltype(H) == ComplexF64
  @test ndims(H) == 2
  @test dim(H) == 100^2

  I_arr = rand(10,10,10)
  I = Tensor(I_arr, (10,10,10))
  @test eltype(I) == Float64
  @test dim(I) == 1000
  @test Array(I) == I_arr

  J = Tensor(2,2)
  K = Tensor(2,2)
  @test Array(J * K) ≈ Array(J) * Array(K) 
end

@testset "Random constructor" begin
  T = randomTensor(2, 2)
  @test dims(T) == (2,2)
  @test eltype(T) == Float64
  @test T[1,1] ≉ 0
  @test norm(T) ≉ 0

  Tc = randomTensor(ComplexF64, 2, 2)
  @test dims(Tc) == (2,2)
  @test eltype(Tc) == ComplexF64
  @test Tc[1,1] ≉ 0
  @test norm(Tc) ≉ 0
end

@testset "Custom inds types" begin
  struct MyInd
    dim::Int
  end
  NDTensors.dim(i::MyInd) = i.dim

  T = Tensor((MyInd(2), MyInd(3), MyInd(4)))
  @test store(T) isa Dense
  @test eltype(T) == Float64
  @test norm(T) == 0
  @test dims(T) == (2, 3, 4)
  @test ndims(T) == 3
  @test inds(T) == (MyInd(2), MyInd(3), MyInd(4))
  T[2, 1, 2] = 1.21
  @test T[2, 1, 2] == 1.21
  @test norm(T) == 1.21

  T = randomTensor(ComplexF64, (MyInd(4), MyInd(3)))
  @test store(T) isa Dense
  @test eltype(T) == ComplexF64
  @test norm(T) > 0
  @test dims(T) == (4, 3)
  @test ndims(T) == 2
  @test inds(T) == (MyInd(4), MyInd(3))

  T2 = 2 * T
  @test eltype(T2) == ComplexF64
  @test store(T2) isa Dense
  @test norm(T2) > 0
  @test norm(T2) / norm(T) ≈ 2
  @test dims(T2) == (4, 3)
  @test ndims(T2) == 2
  @test inds(T2) == (MyInd(4), MyInd(3))

end

nothing
