{-|
Module      : H3.Traversal

Grid traversal allows finding cells in the vicinity of an origin cell, 
and determining how to traverse the grid from one cell to another.
-}
module H3.Traversal
  ( gridDisk
  , gridDiskUnsafe
  , gridDiskDistances
  , gridDiskDistancesSafe
  , gridDiskDistancesUnsafe
  , gridRingUnsafe
  , gridPathCells
  , gridDistance 
  , cellToLocalIj
  , localIjToCell
  ) where

import Data.Int (Int64)
import H3.Internal.H3Api 
  ( H3ErrorCodes
  , H3Index
  , CoordIJ
  , c2hs_gridDistance
  , c2hs_cellToLocalIj
  , c2hs_localIjToCell
  )
import H3.Internal.FFI 
  ( hsGridDisk
  , hsGridDiskUnsafe
  , hsGridDiskDistances 
  , hsGridDiskDistancesSafe 
  , hsGridDiskDistancesUnsafe
  , hsGridRingUnsafe
  , hsGridPathCells
  )
import H3.Internal.Utils (toEither)

-- | gridDisk produces indices within @k@ distance of the @origin@ index.
--   Elements of the output array may be left as zero, which can happen when crossing a pentagon.
gridDisk :: H3Index -- ^ origin
         -> Int     -- ^ k
         -> Either H3ErrorCodes [H3Index]
gridDisk :: H3Index -> Int -> Either H3ErrorCodes [H3Index]
gridDisk H3Index
origin = (Word32, [H3Index]) -> Either H3ErrorCodes [H3Index]
forall a. (Word32, a) -> Either H3ErrorCodes a
toEither ((Word32, [H3Index]) -> Either H3ErrorCodes [H3Index])
-> (Int -> (Word32, [H3Index]))
-> Int
-> Either H3ErrorCodes [H3Index]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. H3Index -> Int -> (Word32, [H3Index])
hsGridDisk H3Index
origin

-- | gridDiskUnsafe produces indexes within @k@ distance of the @origin@ index. 
--   The function returns an error code when one of the returned by this function is a pentagon 
--   or is in the pentagon distortion area. 
--   In this case, the output behavior of the out array is undefined.
gridDiskUnsafe :: H3Index -- ^ origin 
               -> Int     -- ^ k 
               -> Either H3ErrorCodes [H3Index]
gridDiskUnsafe :: H3Index -> Int -> Either H3ErrorCodes [H3Index]
gridDiskUnsafe H3Index
origin = (Word32, [H3Index]) -> Either H3ErrorCodes [H3Index]
forall a. (Word32, a) -> Either H3ErrorCodes a
toEither ((Word32, [H3Index]) -> Either H3ErrorCodes [H3Index])
-> (Int -> (Word32, [H3Index]))
-> Int
-> Either H3ErrorCodes [H3Index]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. H3Index -> Int -> (Word32, [H3Index])
hsGridDiskUnsafe H3Index
origin

-- | gridDiskDistances produces indices within @k@ distance of the @origin@ index.
--    k-ring 0 is defined as the origin index, k-ring 1 is defined as k-ring 0 
--    and all neighboring indices, and so on.
gridDiskDistances :: H3Index -- ^ origin
                  -> Int     -- ^ k
                  -> Either H3ErrorCodes ([H3Index], [Int])
gridDiskDistances :: H3Index -> Int -> Either H3ErrorCodes ([H3Index], [Int])
gridDiskDistances H3Index
origin = (Word32, ([H3Index], [Int]))
-> Either H3ErrorCodes ([H3Index], [Int])
forall a. (Word32, a) -> Either H3ErrorCodes a
toEither ((Word32, ([H3Index], [Int]))
 -> Either H3ErrorCodes ([H3Index], [Int]))
-> (Int -> (Word32, ([H3Index], [Int])))
-> Int
-> Either H3ErrorCodes ([H3Index], [Int])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. H3Index -> Int -> (Word32, ([H3Index], [Int]))
hsGridDiskDistances H3Index
origin 

-- | gridDiskDistancesSafe produces indexes within @k@ distance of the @origin@ index.
gridDiskDistancesSafe :: H3Index -- ^ origin 
                      -> Int     -- ^ k
                      -> Either H3ErrorCodes ([H3Index], [Int])
gridDiskDistancesSafe :: H3Index -> Int -> Either H3ErrorCodes ([H3Index], [Int])
gridDiskDistancesSafe H3Index
origin = (Word32, ([H3Index], [Int]))
-> Either H3ErrorCodes ([H3Index], [Int])
forall a. (Word32, a) -> Either H3ErrorCodes a
toEither ((Word32, ([H3Index], [Int]))
 -> Either H3ErrorCodes ([H3Index], [Int]))
-> (Int -> (Word32, ([H3Index], [Int])))
-> Int
-> Either H3ErrorCodes ([H3Index], [Int])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. H3Index -> Int -> (Word32, ([H3Index], [Int]))
hsGridDiskDistancesSafe H3Index
origin 

-- | gridDiskDistancesUnsafe produces indexes within @k@ distance of the @origin@ index. 
--   Output behavior is undefined when one of the indexes returned by this function is a pentagon 
--   or is in the pentagon distortion area.
gridDiskDistancesUnsafe :: H3Index -- ^ origin
                        -> Int     -- ^ k
                        -> Either H3ErrorCodes ([H3Index], [Int])
gridDiskDistancesUnsafe :: H3Index -> Int -> Either H3ErrorCodes ([H3Index], [Int])
gridDiskDistancesUnsafe H3Index
origin = (Word32, ([H3Index], [Int]))
-> Either H3ErrorCodes ([H3Index], [Int])
forall a. (Word32, a) -> Either H3ErrorCodes a
toEither ((Word32, ([H3Index], [Int]))
 -> Either H3ErrorCodes ([H3Index], [Int]))
-> (Int -> (Word32, ([H3Index], [Int])))
-> Int
-> Either H3ErrorCodes ([H3Index], [Int])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. H3Index -> Int -> (Word32, ([H3Index], [Int]))
hsGridDiskDistancesUnsafe H3Index
origin 

-- | Produces the hollow hexagonal ring centered at @origin@ with sides of length @k@.
--   In this Haskell method, zeros have been removed from the resulting list of H3 indexes.
gridRingUnsafe :: H3Index -- ^ origin
               -> Int     -- ^ k
               -> Either H3ErrorCodes [H3Index]
gridRingUnsafe :: H3Index -> Int -> Either H3ErrorCodes [H3Index]
gridRingUnsafe H3Index
h3index = ([H3Index] -> [H3Index])
-> Either H3ErrorCodes [H3Index] -> Either H3ErrorCodes [H3Index]
forall a b.
(a -> b) -> Either H3ErrorCodes a -> Either H3ErrorCodes b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((H3Index -> Bool) -> [H3Index] -> [H3Index]
forall a. (a -> Bool) -> [a] -> [a]
filter (H3Index -> H3Index -> Bool
forall a. Eq a => a -> a -> Bool
/= H3Index
0)) (Either H3ErrorCodes [H3Index] -> Either H3ErrorCodes [H3Index])
-> (Int -> Either H3ErrorCodes [H3Index])
-> Int
-> Either H3ErrorCodes [H3Index]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word32, [H3Index]) -> Either H3ErrorCodes [H3Index]
forall a. (Word32, a) -> Either H3ErrorCodes a
toEither ((Word32, [H3Index]) -> Either H3ErrorCodes [H3Index])
-> (Int -> (Word32, [H3Index]))
-> Int
-> Either H3ErrorCodes [H3Index]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. H3Index -> Int -> (Word32, [H3Index])
hsGridRingUnsafe H3Index
h3index 

-- | Given two H3 indexes, return the line of indexes between them (inclusive).
--   This function may fail to find the line between two indexes, for example if they are very far apart. 
--   It may also fail when finding distances for indexes on opposite sides of a pentagon.
--
--   Notes:
--
--     * The specific output of this function should not be considered stable across library versions. 
--       The only guarantees the library provides are that the line length will be consistent with the distance method 
--       and that every index in the line will be a neighbor of the preceding index.
--     * Lines are drawn in grid space, and may not correspond exactly to either Cartesian lines or great arcs.
gridPathCells :: H3Index -- ^ start
              -> H3Index -- ^ end
              -> Either H3ErrorCodes [H3Index]
gridPathCells :: H3Index -> H3Index -> Either H3ErrorCodes [H3Index]
gridPathCells H3Index
h3index = (Word32, [H3Index]) -> Either H3ErrorCodes [H3Index]
forall a. (Word32, a) -> Either H3ErrorCodes a
toEither ((Word32, [H3Index]) -> Either H3ErrorCodes [H3Index])
-> (H3Index -> (Word32, [H3Index]))
-> H3Index
-> Either H3ErrorCodes [H3Index]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. H3Index -> H3Index -> (Word32, [H3Index])
hsGridPathCells H3Index
h3index

-- | Provides the distance in grid cells between the two indexes.
--   Returns an error if finding the distance failed. 
--   Finding the distance can fail because the two indexes are not comparable (different resolutions), 
--   too far apart, 
--   or are separated by pentagonal distortion. 
--   This is the same set of limitations as the local IJ coordinate space functions.
gridDistance :: H3Index -- ^ origin
             -> H3Index -- ^ destination 
             -> Either H3ErrorCodes Int64
gridDistance :: H3Index -> H3Index -> Either H3ErrorCodes Int64
gridDistance H3Index
origin = (Word32, Int64) -> Either H3ErrorCodes Int64
forall a. (Word32, a) -> Either H3ErrorCodes a
toEither ((Word32, Int64) -> Either H3ErrorCodes Int64)
-> (H3Index -> (Word32, Int64))
-> H3Index
-> Either H3ErrorCodes Int64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. H3Index -> H3Index -> (Word32, Int64)
c2hs_gridDistance H3Index
origin

-- | Produces local IJ coordinates for an H3 index anchored by an @origin@.
--   The C API has an additional argument mode which is reserved for future expansion and must be set to 0. 
--   The method provided here automatically passes the value. 
--   This function's output is not guaranteed to be compatible across different versions of H3.
cellToLocalIj :: H3Index -- ^ origin
              -> H3Index -- ^ destination
              -> Either H3ErrorCodes CoordIJ
cellToLocalIj :: H3Index -> H3Index -> Either H3ErrorCodes CoordIJ
cellToLocalIj H3Index
origin H3Index
h3 = (Word32, CoordIJ) -> Either H3ErrorCodes CoordIJ
forall a. (Word32, a) -> Either H3ErrorCodes a
toEither ((Word32, CoordIJ) -> Either H3ErrorCodes CoordIJ)
-> (Word32, CoordIJ) -> Either H3ErrorCodes CoordIJ
forall a b. (a -> b) -> a -> b
$ H3Index -> H3Index -> Word32 -> (Word32, CoordIJ)
c2hs_cellToLocalIj H3Index
origin H3Index
h3 Word32
0

-- | Produces an H3 index from local IJ coordinates anchored by an @origin@.
--   The C API has an additional argument mode which is reserved for future expansion and must be set to 0, 
--   and the method defined here automatically passes the value. 
--   This function's output is not guaranteed to be compatible across different versions of H3.
localIjToCell :: H3Index -- ^ origin
              -> CoordIJ -- ^ ij
              -> Either H3ErrorCodes H3Index
localIjToCell :: H3Index -> CoordIJ -> Either H3ErrorCodes H3Index
localIjToCell H3Index
origin CoordIJ
ij = (Word32, H3Index) -> Either H3ErrorCodes H3Index
forall a. (Word32, a) -> Either H3ErrorCodes a
toEither ((Word32, H3Index) -> Either H3ErrorCodes H3Index)
-> (Word32, H3Index) -> Either H3ErrorCodes H3Index
forall a b. (a -> b) -> a -> b
$ H3Index -> CoordIJ -> Word32 -> (Word32, H3Index)
c2hs_localIjToCell H3Index
origin CoordIJ
ij Word32
0