!# This source file is distributed with code Pégase.3.0.1 (2019-02-21).
!# Copyright: Michel Fioc (Michel.Fioc@iap.fr), Sorbonne université, 
!# Institut d'astrophysique de Paris/CNRS, France.
!# 
!# Pégase.3.0.1 is governed by the CeCILL license under French law and abides 
!# by the rules of distribution of free software. You can use, modify and/or 
!# redistribute this software under the terms of the CeCILL license as circulated 
!# by CEA, CNRS and INRIA at "http://www.cecill.info". The text of this license
!# is also available in French and in English in directory "doc_dir/" of this
!# code.
!# 
!# As a counterpart to the access to the source code and to the rights to copy,
!# modify and redistribute it granted by the license, users are provided only
!# with a limited warranty, and the software's author, the holder of the
!# economic rights, and the successive licensors have only limited
!# liability. 
!# 
!# The fact that you are presently reading this means that you have had
!# knowledge of the CeCILL license and that you accept its terms.
!#====================================================================== 

module mod_remove_duplicates

  implicit none
  private
  public :: remove_duplicates

contains

!#======================================================================
  subroutine remove_duplicates(string, n_strings, back)

    use mod_heap_index, only : heap_index
    
    implicit none
    character(len=*), dimension(:), pointer :: string
    integer, intent(inout) :: n_strings   
    logical, intent(in) :: back
!#......................................................................
    integer :: i, n_strings_tmp, n_removed, n
    integer, dimension(:), allocatable :: idx, unique
    logical, dimension(:), allocatable :: duplicate, removed
    character(len=len(string)), dimension(:), allocatable :: string_tmp
!#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    
    n_strings_tmp = n_strings
    allocate(string_tmp(n_strings_tmp))
    string_tmp(:) = string(:)

    allocate(idx(n_strings_tmp))
    call heap_index(string_tmp, idx)

    allocate(duplicate(n_strings_tmp))
    duplicate(:) = .false.
    allocate(unique(n_strings_tmp))
    unique(:) = (/(i, i=1, n_strings_tmp)/)
    n_removed = 0
    if (back) then
       do i = n_strings_tmp, 2, -1
          if (string_tmp(idx(i)) == string_tmp(idx(i-1))) then
             duplicate(idx(i)) = .true.
             duplicate(idx(i-1)) = .true.
             unique(idx(i-1)) = unique(idx(i))
             n_removed = n_removed+1
          endif
       enddo
    else
       do i = 2, n_strings_tmp
          if (string_tmp(idx(i)) == string_tmp(idx(i-1))) then
             duplicate(idx(i)) = .true.
             duplicate(idx(i-1)) = .true.
             unique(idx(i)) = unique(idx(i-1))
             n_removed = n_removed+1
          endif
       enddo
    endif

    allocate(removed(n_strings_tmp))
    removed(1:n_strings_tmp) = .false.
    n_strings = n_strings_tmp-n_removed
    deallocate(string)
    allocate(string(n_strings))
    if (back) then
       n = n_strings+1
       do i = n_strings_tmp, 1, -1
          if (.not.duplicate(i)) then
             n = n-1
             string(n) = string_tmp(i)
          else if (.not.removed(unique(i))) then
             n = n-1
             string(n) = string_tmp(i)
             removed(unique(i)) = .true.
          endif
       enddo
    else
       n = 0
       do i = 1, n_strings_tmp
          if (.not.duplicate(i)) then
             n = n+1
             string(n) = string_tmp(i)
          else if (.not.removed(unique(i))) then
             n = n+1
             string(n) = string_tmp(i)
             removed(unique(i)) = .true.
          endif
       enddo
    endif

    deallocate(string_tmp)
    deallocate(idx)
    deallocate(duplicate)
    deallocate(unique)
    deallocate(removed)

  end subroutine remove_duplicates

end module mod_remove_duplicates
