module moduleMeshInputText
  !The mesh is stored as a column-wise text file.
  !Aimed for simple geometries in 1D

  contains
    !Inits the text mesh
    subroutine initText(self)
      use moduleMesh
      use moduleMeshOutputText
      implicit none

      class(meshGeneric), intent(inout), target:: self 

      if (associated(meshForMCC,self)) then
        self%printColl => printCollText

      end if

      select type(self)
      type is (meshParticles)
        self%printOutput  => printOutputText
        self%printEM      => printEMText
        self%printAverage => printAverageText

        self%readInitial  => readInitialText

      end select

      self%readMesh => readText

    end subroutine initText

    !Reads the text mesh
    subroutine readText(self, filename)
      use moduleMesh
      use moduleMesh1DCart
      use moduleMesh1DRad
      use moduleErrors
      implicit none

      class(meshGeneric), intent(inout):: self
      character(:), allocatable, intent(in):: filename !Dummy file, not used
      integer:: fileID, reason
      character(len=256):: line
      integer:: nNodes
      real(8):: r(1:3) !dummy 3D coordinate
      integer:: physicalID
      integer:: n, c
      integer, allocatable:: p(:)

      fileID = 10

      open(fileID, file=trim(filename))

      !Skip header
      read(fileID, *)

      !Get number of nodes
      nNodes = 0
      do
        read(fileID, *, iostat=reason) line

        if (reason > 0) then
          call criticalError('Error reading mesh file', 'readText')

        else if (reason < 0) then
          exit

        else if (len(line) > 0) then
          nNodes = nNodes + 1

        end if

      end do

      if (nNodes == 0) then
        call criticalError('No nodes read in mesh file', 'readText')

      end if

      self%numNodes = nNodes
      allocate(self%nodes(1:self%numNodes))

      SELECT TYPE(self)
      TYPE IS(meshParticles)
        ALLOCATE(self%K(1:self%numNodes, 1:self%numNodes))
        ALLOCATE(self%IPIV(1:self%numNodes, 1:self%numNodes))
        self%K = 0.D0
        self%IPIV = 0

      END SELECT

      self%numCells = nNodes - 1
      allocate(self%cells(1:self%numCells))

      select type(self)
      type is (meshParticles)
        self%numEdges = 2

        allocate(self%edges(1:self%numEdges))

      end select

      !Read the mesh now
      rewind(fileID)
      
      !Skip header
      read(fileID, *)

      !Allocate nodes and edges
      do n = 1, self%numNodes
        r = 0.D0

        read(fileID, *) r(1), physicalID

        select case(self%geometry)
        case("Cart")
          allocate(meshNode1DCart:: self%nodes(n)%obj)

        case("Rad")
          allocate(meshNode1DRad:: self%nodes(n)%obj)

        end select

        !Init nodes
        call self%nodes(n)%obj%init(n, r)

        !Allocate edges if required)
        select type(self)
        type is (meshParticles)
          if ((physicalID == 1) .or. (physicalID == 2)) then
            select case(self%geometry)
            case("Cart")
              allocate(meshEdge1DCart:: self%edges(physicalID)%obj)

            case("Rad")
              allocate(meshEdge1DRad:: self%edges(physicalID)%obj)
            
            end select

            allocate(p(1))
            p(1) = n

            call self%edges(physicalID)%obj%init(physicalID, p, physicalID)

            deallocate(p)

          end if

        end select

      end do

      !Allocate cells
      n = 1
      allocate(p(1:2))
      do c = 1, self%numCells
        p(1) = n
        n = n + 1
        p(2) = n
        
        select case(self%geometry)
        case("Cart")
          allocate(meshCell1DCartSegm:: self%cells(c)%obj)

        case("Rad")
          allocate(meshCell1DRadSegm:: self%cells(c)%obj)

        end select

        call self%cells(c)%obj%init(c, p, self%nodes)


      end do
      deallocate(p)

      close(fileID)

      !Call mesh connectivity
      CALL self%connectMesh

    end subroutine readText

    subroutine readInitialText(filename, density, velocity, temperature)
      use moduleErrors
      implicit none

      character(:), allocatable, intent(in):: filename
      real(8), allocatable, intent(out), dimension(:):: density
      real(8), allocatable, intent(out), dimension(:,:):: velocity
      real(8), allocatable, intent(out), dimension(:):: temperature
      integer:: fileID, reason
      character(len=256):: line
      integer:: nNodes
      integer:: n

      fileID = 10

      open(fileID, file=trim(filename))

      do 
        read(fileID, *, iostat=reason) line
      
        if (reason > 0) then
          call criticalError('Error reading mesh file', 'readText')

        else if (reason < 0) then
          exit

        else if (len(line) > 0) then
          nNodes = nNodes + 1

        end if

      end do

      allocate(density(1:nNodes))
      allocate(velocity(1:nNodes, 1:3))
      allocate(temperature(1:nNodes))

      rewind(fileID)

      do n = 1, nNodes
        read(fileID, *) density(n), velocity(n, 1:3), temperature(n)

      end do

      close(fileID)

    end subroutine readInitialText

end module moduleMeshInputText
