module gms_input_var
  use datatype
  use model_info
  use mem_manager
  implicit none

  interface input_var
     module procedure input_var_x
     module procedure input_var_y
     module procedure input_var_z
     module procedure input_var_xy
     module procedure input_var_xz
     module procedure input_var_yz
     module procedure input_var_xyz
  end interface

contains
  subroutine input_var_x(var, output)
    real(8), dimension(:), intent(in) :: var
    type(var_x), intent(inout) :: output
    integer :: new_id

    if ( size(var,1) /= size(work_x,1) ) stop '[input_var_x]size dimension1'

    linked_counter_x( output%id ) = linked_counter_x( output%id ) -1 

    if ( linked_counter_x( output%id ) == 0 ) then 
       free_mask_x( output%id ) = .true. 
    end if 

    call get_new_id_x(new_id)
    output%id = new_id 


       linked_counter_x( output%id ) = linked_counter_x( output%id ) + 1 

    if( free_mask_x( output%id )  ) then 
       free_mask_x( output%id ) = .false.
    end if 

    work_x(:,1,1,output%id) = var(:)

  end subroutine input_var_x

  subroutine input_var_y(var, output)
    real(8), dimension(:), intent(in) :: var
    type(var_y), intent(inout) :: output
    integer :: new_id

    if ( size(var,1) /= size(work_y,2) ) stop '[input_var_y]size dimension1'

    linked_counter_y( output%id ) = linked_counter_y( output%id ) -1 

    if ( linked_counter_y( output%id ) == 0 ) then 
       free_mask_y( output%id ) = .true. 
    end if 

    call get_new_id_y(new_id)
    output%id = new_id 

       linked_counter_y( output%id ) = linked_counter_y( output%id ) + 1 

    if( free_mask_y( output%id )  ) then 
       free_mask_y( output%id ) = .false.
    end if 

    work_y(1,:,1,output%id) = var(:)

  end subroutine input_var_y

  subroutine input_var_z(var, output)
    real(8), dimension(:), intent(in) :: var
    type(var_z), intent(inout) :: output
    integer :: new_id

    if ( size(var,1) /= size(work_z,3) ) stop '[input_var_z]size dimension1'

    linked_counter_z( output%id ) = linked_counter_z( output%id ) -1 

    if ( linked_counter_z( output%id ) == 0 ) then 
       free_mask_z( output%id ) = .true. 
    end if 

    call get_new_id_z(new_id)
    output%id = new_id 

       linked_counter_z( output%id ) = linked_counter_z( output%id ) + 1 

    if( free_mask_z( output%id )  ) then 
       free_mask_z( output%id ) = .false.
    end if 

    work_z(1,1,:,output%id) = var(:)

  end subroutine input_var_z

  subroutine input_var_xy(var, output)
    real(8), dimension(:,:), intent(in) :: var
    type(var_xy), intent(inout) :: output
    integer :: new_id

    if ( size(var,1) /= size(work_xy,1) ) stop '[input_var_xy]size dimension1'
    if ( size(var,2) /= size(work_xy,2) ) stop '[input_var_xy]size dimension2'

    linked_counter_xy( output%id ) = linked_counter_xy( output%id ) -1 

    if ( linked_counter_xy( output%id ) == 0 ) then 
       free_mask_xy( output%id ) = .true. 
    end if 

    call get_new_id_xy(new_id)
    output%id = new_id 

       linked_counter_xy( output%id ) = linked_counter_xy( output%id ) + 1 

    if( free_mask_xy( output%id )  ) then 
       free_mask_xy( output%id ) = .false.
    end if 

    work_xy(:,:,1,output%id) = var(:,:)

  end subroutine input_var_xy

  subroutine input_var_xz(var, output)
    real(8), dimension(:,:), intent(in) :: var
    type(var_xz), intent(inout) :: output
    integer :: new_id

    if ( size(var,1) /= size(work_xz,1) ) stop '[input_var_xz]size dimension1'
    if ( size(var,2) /= size(work_xz,3) ) stop '[input_var_xz]size dimension2'

    linked_counter_xz( output%id ) = linked_counter_xz( output%id ) -1 

    if ( linked_counter_xz( output%id ) == 0 ) then 
       free_mask_xz( output%id ) = .true. 
    end if 

    call get_new_id_xz(new_id)
    output%id = new_id 

       linked_counter_xz( output%id ) = linked_counter_xz( output%id ) + 1 

    if( free_mask_xz( output%id )  ) then 
       free_mask_xz( output%id ) = .false.
    end if 

    work_xz(:,1,:,output%id) = var(:,:)

  end subroutine input_var_xz

  subroutine input_var_yz(var, output)
    real(8), dimension(:,:), intent(in) :: var
    type(var_yz), intent(inout) :: output
    integer :: new_id

    if ( size(var,1) /= size(work_yz,2) ) stop '[input_var_yz]size dimension1'
    if ( size(var,2) /= size(work_yz,3) ) stop '[input_var_yz]size dimension2'

    linked_counter_yz( output%id ) = linked_counter_yz( output%id ) -1 

    if ( linked_counter_yz( output%id ) == 0 ) then 
       free_mask_yz( output%id ) = .true. 
    end if 

    call get_new_id_yz(new_id)
    output%id = new_id 

       linked_counter_yz( output%id ) = linked_counter_yz( output%id ) + 1 

    if( free_mask_yz( output%id )  ) then 
       free_mask_yz( output%id ) = .false.
    end if 


    work_yz(1,:,:,output%id) = var(:,:)

  end subroutine input_var_yz

  subroutine input_var_xyz(var, output)
    real(8), dimension(:,:,:), intent(in) :: var
    type(var_xyz), intent(inout) :: output
    integer :: new_id

    if ( size(var,1) /= size(work_xyz,1) ) stop '[input_var_xyz]size dimension1'
    if ( size(var,2) /= size(work_xyz,2) ) stop '[input_var_xyz]size dimension2'
    if ( size(var,3) /= size(work_xyz,3) ) stop '[input_var_xyz]size dimension3'

    linked_counter_xyz( output%id ) = linked_counter_xyz( output%id ) -1 

    if ( linked_counter_xyz( output%id ) == 0 ) then 
       free_mask_xyz( output%id ) = .true. 
    end if 

    call get_new_id_xyz(new_id)
    output%id = new_id 

       linked_counter_xyz( output%id ) = linked_counter_xyz( output%id ) + 1 

    if( free_mask_xyz( output%id )  ) then 
       free_mask_xyz( output%id ) = .false.
    end if 


    work_xyz(:,:,:,output%id) = var(:,:,:)

  end subroutine input_var_xyz

end module gms_input_var
