open import Level using (Level; levelOfType)
open import Algebra
open import Function
open import Data.Bool using (Bool; if_then_else_; T)
open import Data.Nat as  using ()
open import Data.Product using (Σ-syntax; -,_; _,_)
open import Data.Maybe as Maybe
open import Data.Product
open import Data.Fin
open import Data.Fin.Patterns
open import Data.Vec.Functional
open import Relation.Binary
open import Relation.Nullary
import Data.Vec.Functional.Relation.Binary.Equality.Setoid as ≋-props

module Vector.Base where

private variable
  c  : Level
  A B : Set 
  m n : 
  xs ys zs : Vector A n

infixl 6 _[_]≔_

_[_]≔_ : Vector A n  Fin n  A  Vector A n
xs [ i ]≔ x = updateAt xs i (const x)

swapV : Vector A n  (i j : Fin n)  Vector A n
swapV xs i j = xs [ i ]≔ xs j [ j ]≔ xs i

[_] : A  Vector A 1
[ x ] _ = x

ListVec : Set   Set _
ListVec A = Σ[ n   ] Vector A n

filter : (A  Bool)  Vector A n  ListVec A
filter {n = ℕ.zero} f xs = -, []
filter {n = ℕ.suc n} f xs = let x = xs 0F ; _ , fxs = filter f (tail xs) in
  if f x then -, x  fxs else -, fxs

module SetoidProps (S : Setoid c ) where
  open module  = Setoid S
  open ≋-props S

  private variable
    x y : Carrier
    xs‵ ys‵ : Vector Carrier n

  ≋-cons : x  y  xs‵  ys‵  (x  xs‵)  (y  ys‵)
  ≋-cons x≈y xs≋ys zero = x≈y
  ≋-cons x≈y xs≋ys (suc i) = xs≋ys i

  ≋-consˡ : xs‵  ys‵  (x  xs‵)  (x  ys‵)
  ≋-consˡ = ≋-cons ≈.refl

Monotone : Vector (Fin m) n  Set _
Monotone xs = xs Preserves _<_  _<_

findFirst : Vector A n  (A  Bool)  Maybe (Fin n × A)
findFirst {n = ℕ.zero} xs f = nothing
findFirst {n = ℕ.suc n} xs f = if f (xs zero) then just (zero , (xs zero))
  else Maybe.map  (i , a)  suc i , a) (findFirst (tail xs) f)

findFirstElement : Vector A n  (A  Bool)  Maybe A
findFirstElement = Maybe.map proj₂ ∘₂ findFirst

findFirstWithProp : Vector A n  (A  Maybe B)  Maybe (Fin n × B)
findFirstWithProp {n = ℕ.zero} xs f = nothing
findFirstWithProp {n = ℕ.suc n} xs f = maybe′  x  just (zero , x)) (Maybe.map  (i , a)  suc i , a)
  (findFirstWithProp (tail xs) f)) $ f $ xs zero

appendLast : Vector A n  A  Vector A (ℕ.suc n)
appendLast {n = ℕ.zero} xs a i = a
appendLast {n = ℕ.suc n} xs a 0F = xs 0F
appendLast {n = ℕ.suc n} xs a (suc i) = appendLast (tail xs) a i