!
! Matching on base of looking for nearest stars
!
!
! Copyright © 2017 F.Hroch (hroch@physics.muni.cz)
!
! This file is part of Munipack.
!
! Munipack is free software: you can redistribute it and/or modify
! it under the terms of the GNU General Public License as published by
! the Free Software Foundation, either version 3 of the License, or
! (at your option) any later version.
!
! Munipack is distributed in the hope that it will be useful,
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with Munipack.  If not, see <http://www.gnu.org/licenses/>.
!

module nearmatch

  use iso_fortran_env

  implicit none

  integer, parameter, private :: dbl = selected_real_kind(15)

contains

  subroutine listmatch(type,alpha,delta,pmalpha,pmdelta,xx,yy,epoch,jd, &
       acen,dcen,xc,yc,scale,pa,refl,tol,i1,i2,status)

    use astrotrafo

    character(len=*), intent(in) :: type
    real(dbl), dimension(:), intent(in) :: alpha,delta,pmalpha,pmdelta,xx,yy
    real(dbl), intent(in) :: acen,dcen,xc,yc,scale,pa,refl,tol,epoch,jd
    integer, dimension(:), allocatable, intent(out) :: i1,i2
    logical, intent(out) :: status
    real(dbl), dimension(:), allocatable :: x,y,u,v
    integer, dimension(:), allocatable :: id1,id2
    type(AstroTrafoProj) :: t
    real(dbl) :: smin,smin0,s,dt
    integer :: nsize,msize,n,i,j,idx
    logical :: found

    status = .false.

    if( size(alpha) /= size(delta) .or. size(xx) /= size(yy) .or. &
        size(alpha) /= size(pmalpha) .or. size(pmalpha) /= size(pmdelta) ) stop 666

    allocate(x(size(xx)),y(size(yy)))
    x = xx
    y = yy

    ! apparent coordinates
    dt = (jd - epoch)/365.25_dbl

    ! select maximum amount of stars by list
    nsize = size(alpha)
    msize = size(x)
    allocate(u(nsize),v(nsize),id1(nsize),id2(nsize))

    call trafo_init(t,type,acen,dcen)
    call proj(t,alpha+dt*pmalpha,delta+dt*pmdelta,u,v)
    call trafo_init(t,xcen=xc,ycen=yc,scale=1/scale,rot=pa,refl=refl)
    call invaffine(t,xx,yy,x,y)

    smin0 = tol

    n = 0
    do i = 1, nsize
       smin = smin0
!       write(*,'(i5,5f15.5)') i,u(i),v(i),alpha(i),delta(i),smin
!       write(*,*) alpha(i),delta(i),smin
       idx = 0
       do j = 1, msize
!          write(*,*) x(j),y(j),smin
          s = sqrt((u(i) - x(j))**2 + (v(i) - y(j))**2)
          if( s < smin ) then
             ! the nearest and brighest star (on flux-sorted list)
             smin = s
             idx = j
          end if
       end do
       if( idx > 0 ) then

          ! check whatever the star is already presented,
          ! it will be ignored, because brighter ones are prefered
          ! (and we are supposing flux-sorted lists).
          found = .false.
          do j = 1, n
             if( idx == id2(j) ) then
                found = .true.
                goto 99
             end if
          end do
99        continue

          if( .not. found ) then
             n = n + 1
             id1(n) = i
             id2(n) = idx
          end if


!          if( debug ) write(*,'(f10.3,2i5,2f15.2)') smin,i,idx,u(i)-x(idx),v(i)-y(idx)

          if( n == size(id1) ) goto 20
       end if
    end do
20 continue

    allocate(i1(n),i2(n))
    i1 = id1(1:n)
    i2 = id2(1:n)

    deallocate(id1,id2,u,v,x,y)

    status = n > 0

  end subroutine listmatch


end module nearmatch
