{-# OPTIONS --safe #-}
module Cubical.Data.List.FinData where

open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Function
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Isomorphism
open import Cubical.Data.List
open import Cubical.Data.FinData
open import Cubical.Data.Empty as 
open import Cubical.Data.Sigma.Properties
open import Cubical.Data.Nat

variable
   : Level
  A B : Type 

-- copy-paste from agda-stdlib
lookup :  (xs : List A)  Fin (length xs)  A
lookup (x  xs) zero    = x
lookup (x  xs) (suc i) = lookup xs i

tabulate :  n  (Fin n  A)  List A
tabulate zero ^a = []
tabulate (suc n) ^a = ^a zero  tabulate n (^a  suc)

length-tabulate :  n  (^a : Fin n  A)  length (tabulate n ^a)  n
length-tabulate zero ^a = refl
length-tabulate (suc n) ^a = cong suc (length-tabulate n (^a  suc))

tabulate-lookup :  (xs : List A)  tabulate (length xs) (lookup xs)  xs
tabulate-lookup [] = refl
tabulate-lookup (x  xs) = cong (x ∷_) (tabulate-lookup xs)

lookup-tabulate :  n  (^a : Fin n  A)
   PathP  i  (Fin (length-tabulate n ^a i)  A)) (lookup (tabulate n ^a)) ^a
lookup-tabulate (suc n) ^a i zero = ^a zero
lookup-tabulate (suc n) ^a i (suc p) = lookup-tabulate n (^a  suc) i p

open Iso

lookup-tabulate-iso : (A : Type )  Iso (List A) (Σ[ n   ] (Fin n  A))
fun (lookup-tabulate-iso A) xs = (length xs) , lookup xs
inv (lookup-tabulate-iso A) (n , f) = tabulate n f
leftInv (lookup-tabulate-iso A) = tabulate-lookup
rightInv (lookup-tabulate-iso A) (n , f) =
  ΣPathP ((length-tabulate n f) , lookup-tabulate n f)

lookup-tabulate-equiv : (A : Type )  List A  (Σ[ n   ] (Fin n  A))
lookup-tabulate-equiv A = isoToEquiv (lookup-tabulate-iso A)

lookup-map :  (f : A  B) (xs : List A)
   (p0 : Fin (length (map f xs)))
   (p1 : Fin (length xs))
   (p : PathP  i  Fin (length-map f xs i)) p0 p1)
   lookup (map f xs) p0  f (lookup xs p1)
lookup-map f (x  xs) zero zero p = refl
lookup-map f (x  xs) zero (suc p1) p = ⊥.rec (znotsP p)
lookup-map f (x  xs) (suc p0) zero p = ⊥.rec (snotzP p)
lookup-map f (x  xs) (suc p0) (suc p1) p = lookup-map f xs p0 p1 (injSucFinP p)