\begin{code}

{-# OPTIONS --safe --without-K #-}

open import MLTT.Spartan renaming (_+_ to _∔_)

open import Integers.Abs
open import Integers.Addition
open import Integers.Type
open import Integers.Multiplication
open import Integers.Negation
open import Naturals.Multiplication renaming (_*_ to _ℕ*_)
open import Naturals.Parity
open import Naturals.Properties
open import UF.Subsingletons

module Integers.Parity where

ℤeven ℤodd :   𝓤₀ ̇
ℤeven z = even (abs z)
ℤodd  z = odd (abs z)

ℤeven-not-odd : (n : )  ℤeven n  ¬ ℤodd n
ℤeven-not-odd n = even-not-odd (abs n)

ℤodd-not-even : (n : )  ℤodd n  ¬ ℤeven n
ℤodd-not-even n = odd-not-even (abs n)

ℤzero-not-odd : (n : )  ℤodd n  ¬ (n  pos 0)
ℤzero-not-odd (pos 0)        on e = on
ℤzero-not-odd (pos (succ n)) on e = positive-not-zero n (pos-lc e)

ℤeven-is-prop : (n : )  is-prop (ℤeven n)
ℤeven-is-prop n = even-is-prop (abs n)

ℤodd-is-prop : (n : )  is-prop (ℤodd n)
ℤodd-is-prop n = odd-is-prop (abs n)

ℤeven-or-odd : (n : )  ℤeven n  ℤodd n
ℤeven-or-odd (pos 0)            = inl 
ℤeven-or-odd (pos (succ x))     = ℤeven-or-odd (negsucc x)
ℤeven-or-odd (negsucc 0)        = inr 
ℤeven-or-odd (negsucc (succ x)) = ℤeven-or-odd (pos x)

ℤeven-or-odd-is-prop : (n : )  is-prop (ℤeven n  ℤodd n)
ℤeven-or-odd-is-prop n = even-or-odd-is-prop (abs n)

ℤsucc-even-is-odd : (n : )  ℤeven n  ℤodd (succℤ n)
ℤsucc-even-is-odd (pos x)            = succ-even-is-odd (abs (pos x))
ℤsucc-even-is-odd (negsucc 0)        = id
ℤsucc-even-is-odd (negsucc (succ x)) = id

ℤpred-even-is-odd : (n : )  ℤeven n  ℤodd (predℤ n)
ℤpred-even-is-odd (pos 0)        = id
ℤpred-even-is-odd (pos (succ x)) = id
ℤpred-even-is-odd (negsucc x)    = id

ℤsucc-odd-is-even : (n : )  ℤodd n  ℤeven (succℤ n)
ℤsucc-odd-is-even (pos x)            = succ-odd-is-even (abs (pos x))
ℤsucc-odd-is-even (negsucc 0)        = id
ℤsucc-odd-is-even (negsucc (succ x)) = id

ℤpred-odd-is-even : (n : )  ℤodd n  ℤeven (predℤ n)
ℤpred-odd-is-even (pos 0)        = id
ℤpred-odd-is-even (pos (succ x)) = id
ℤpred-odd-is-even (negsucc x)    = id

ℤodd-succ-succ : (n : )  ℤodd n  ℤodd (succℤ (succℤ n))
ℤodd-succ-succ (pos x)                   = odd-succ-succ (abs (pos x))
ℤodd-succ-succ (negsucc 0)               = id
ℤodd-succ-succ (negsucc 1)               = id
ℤodd-succ-succ (negsucc (succ (succ x))) = id

ℤodd-pred-pred : (n : )  ℤodd n  ℤodd (predℤ (predℤ n))
ℤodd-pred-pred (pos 0)               = id
ℤodd-pred-pred (pos 1)               = id
ℤodd-pred-pred (pos (succ (succ x))) = id
ℤodd-pred-pred (negsucc x)           = id

ℤodd-succ-succ' : (n : )  ℤodd (succℤ (succℤ n))  ℤodd n
ℤodd-succ-succ' (pos x)                   = odd-succ-succ' (abs (pos x))
ℤodd-succ-succ' (negsucc 0)               = id
ℤodd-succ-succ' (negsucc 1)               = id
ℤodd-succ-succ' (negsucc (succ (succ x))) = id

ℤodd-pred-pred' : (n : )  ℤodd (predℤ (predℤ n))  ℤodd n
ℤodd-pred-pred' (pos 0)               = id
ℤodd-pred-pred' (pos 1)               = id
ℤodd-pred-pred' (pos (succ (succ x))) = id
ℤodd-pred-pred' (negsucc x)           = id

ℤeven-succ-succ : (n : )  ℤeven n  ℤeven (succℤ (succℤ n))
ℤeven-succ-succ (pos x)                   = even-succ-succ (abs (pos x))
ℤeven-succ-succ (negsucc 0)               = id
ℤeven-succ-succ (negsucc 1)               = id
ℤeven-succ-succ (negsucc (succ (succ x))) = id

ℤeven-pred-pred : (n : )  ℤeven n  ℤeven (predℤ (predℤ n))
ℤeven-pred-pred (pos 0)               = id
ℤeven-pred-pred (pos 1)               = id
ℤeven-pred-pred (pos (succ (succ x))) = id
ℤeven-pred-pred (negsucc x)           = id

ℤeven-succ-succ' : (n : )  ℤeven (succℤ (succℤ n))  ℤeven n
ℤeven-succ-succ' (pos x)                   = even-succ-succ' (abs (pos x))
ℤeven-succ-succ' (negsucc 0)               = id
ℤeven-succ-succ' (negsucc 1)               = id
ℤeven-succ-succ' (negsucc (succ (succ x))) = id

ℤeven-pred-pred' : (n : )  ℤeven (predℤ (predℤ n))  ℤeven n
ℤeven-pred-pred' (pos 0)               = id
ℤeven-pred-pred' (pos 1)               = id
ℤeven-pred-pred' (pos (succ (succ x))) = id
ℤeven-pred-pred' (negsucc x)           = id

ℤeven*even : (n m : )  ℤeven n  ℤeven m  ℤeven (n * m)
ℤeven*even n m en em = transport even I II
 where
  I : abs n ℕ* abs m  abs (n * m)
  I = abs-over-mult n m ⁻¹
  II : even (abs n ℕ* abs m)
  II = even*even (abs n) (abs m) en em

ℤodd*odd : (n m : )  ℤodd n  ℤodd m  ℤodd (n * m)
ℤodd*odd n m on om = transport odd I II
 where
  I : abs n ℕ* abs m  abs (n * m)
  I = abs-over-mult n m ⁻¹
  II : odd (abs n ℕ* abs m)
  II = odd*odd (abs n) (abs m) on om

ℤeven*odd : (n m : )  ℤeven n  ℤodd m  ℤeven (n * m)
ℤeven*odd n m en om = transport even I II
 where
  I : abs n ℕ* abs m  abs (n * m)
  I = (abs-over-mult n m ⁻¹)
  II : even (abs n ℕ* abs m)
  II = (even*odd (abs n) (abs m) en om)

ℤodd*even : (n m : )  ℤodd n  ℤeven m  ℤeven (n * m)
ℤodd*even n m on em = transport ℤeven (ℤ*-comm m n) (ℤeven*odd m n em on)

ℤeven-neg : (n : )  ℤeven n  ℤeven (- n)
ℤeven-neg n = transport even (abs-removes-neg-sign n)

ℤodd-neg : (n : )  ℤodd n  ℤodd (- n)
ℤodd-neg n = transport odd (abs-removes-neg-sign n)

ℤeven+even : (n m : )  ℤeven n  ℤeven m  ℤeven (n + m)
ℤeven+even n (pos 0)                   en em = en
ℤeven+even n (pos 1)                   en em = 𝟘-elim em
ℤeven+even n (pos (succ (succ m)))     en em = ℤeven-succ-succ (n + pos m) (ℤeven+even n (pos m) en em)
ℤeven+even n (negsucc 0)               en em = 𝟘-elim em
ℤeven+even n (negsucc 1)               en em = ℤeven-pred-pred n en
ℤeven+even n (negsucc (succ (succ m))) en em = ℤeven-pred-pred (n + negsucc m) (ℤeven+even n (negsucc m) en em)

ℤeven+odd : (n m : )  ℤeven n  ℤodd m  ℤodd (n + m)
ℤeven+odd n (pos 0)                   on em = 𝟘-elim em
ℤeven+odd n (pos 1)                   on em = ℤsucc-even-is-odd n on
ℤeven+odd n (pos (succ (succ m)))     on em = ℤodd-succ-succ (n + pos m) (ℤeven+odd n (pos m) on em)
ℤeven+odd n (negsucc 0)               on em = ℤpred-even-is-odd n on
ℤeven+odd n (negsucc 1)               on em = 𝟘-elim em
ℤeven+odd n (negsucc (succ (succ m))) on em = ℤodd-pred-pred (n +negsucc m) (ℤeven+odd n (negsucc m) on em)

ℤodd+even : (n m : )  ℤodd n  ℤeven m  ℤodd (n + m)
ℤodd+even n m on em = transport ℤodd (ℤ+-comm m n) (ℤeven+odd m n em on)

ℤodd+odd : (n m : )  ℤodd n  ℤodd m  ℤeven (n + m)
ℤodd+odd n (pos 0)                   on om = 𝟘-elim om
ℤodd+odd n (pos 1)                   on om = ℤsucc-odd-is-even n on
ℤodd+odd n (pos (succ (succ m)))     on om = ℤeven-succ-succ (n + pos m) (ℤodd+odd n (pos m) on om)
ℤodd+odd n (negsucc 0)               on om = ℤpred-odd-is-even n on
ℤodd+odd n (negsucc 1)               on om = 𝟘-elim om
ℤodd+odd n (negsucc (succ (succ m))) on om = ℤeven-pred-pred (n + negsucc m) (ℤodd+odd n (negsucc m) on om)

evenℕ-to-ℤ : (n : )  even n  ℤeven (pos n)
evenℕ-to-ℤ n = id

evenℕ-to-ℤ' : (n : )  even n  ℤeven (- pos n)
evenℕ-to-ℤ' 0        = id
evenℕ-to-ℤ' (succ n) = id

ℤmultiple-of-two-even-lemma-pos : (n : ) (k : )  n  pos 2 * pos k  ℤeven n
ℤmultiple-of-two-even-lemma-pos (pos n) k e = ℕ-induction base step k
 where
  base : even n
  base = multiple-of-two-even-lemma n k I
   where
    I : n  2 ℕ* k
    I = pos-lc (e  pos-multiplication-equiv-to-ℕ 2 k)
  step : (k : )  even n  even n
  step k = id
ℤmultiple-of-two-even-lemma-pos (negsucc n) k e = 𝟘-elim (negsucc-not-pos (e  pos-multiplication-equiv-to-ℕ 2 k))

ℤmultiple-of-two-even-lemma-neg : (n : )  (k : )  n  pos 2 * negsucc k  ℤeven n
ℤmultiple-of-two-even-lemma-neg (pos n)     k e = 𝟘-elim (pos-not-negsucc (e  pr₂ (pos-times-negative 1 k)))
ℤmultiple-of-two-even-lemma-neg (negsucc n) k e = ℕ-induction base step k
 where
  base : even (succ n)
  base = II
   where
    I : - pos (succ n)  - pos (2 ℕ* succ k)
    I = negsucc n              =⟨ e                                                
        pos 2 * negsucc k      =⟨ negation-dist-over-mult (pos 2) (pos (succ k))   
        - pos 2 * pos (succ k) =⟨ ap -_ (pos-multiplication-equiv-to-ℕ 2 (succ k)) 
        - pos (2 ℕ* succ k)    
    II : even (succ n)
    II = multiple-of-two-even-lemma (succ n) (succ k) (pos-lc (negatives-equal (pos (succ n)) (pos (2 ℕ* succ k)) I))
  step : (k : )  odd n  odd n
  step k = id

ℤmultiple-of-two-even-lemma : (n k : )  n  pos 2 * k  ℤeven n
ℤmultiple-of-two-even-lemma n (pos k)     e = ℤmultiple-of-two-even-lemma-pos n k e
ℤmultiple-of-two-even-lemma n (negsucc k) e = ℤmultiple-of-two-even-lemma-neg n k e

ℤmultiple-of-two-even : (n : )  Σ k   , n  pos 2 * k  ℤeven n
ℤmultiple-of-two-even n (k , e) = ℤmultiple-of-two-even-lemma n k e

ℤsucc-multiple-of-two-odd : (n k : )  n  succℤ (pos 2 * k)  ℤodd n
ℤsucc-multiple-of-two-odd n k e = transport ℤodd (succpredℤ n) I
 where
  I : ℤodd (succℤ (predℤ n))
  I = ℤsucc-even-is-odd (predℤ n) (transport ℤeven (III ⁻¹) II)
   where
    II : ℤeven (pos 2 * k)
    II = ℤmultiple-of-two-even (pos 2 * k) (k , refl)
    III : predℤ n  pos 2 * k
    III = predℤ n                    =⟨ ap predℤ e            
          predℤ (succℤ (pos 2 * k))  =⟨ predsuccℤ (pos 2 * k) 
          pos 2 * k 

ℤeven-is-multiple-of-two : (n : )  ℤeven n  Σ k   , n  pos 2 * k
ℤeven-is-multiple-of-two (pos n)     en = I (even-is-multiple-of-two n en)
 where
  I : Σ k   , n  2 ℕ* k  Σ k   , pos n  pos 2 * k
  I (k , e) = (pos k) , (ap pos e  pos-multiplication-equiv-to-ℕ 2 k ⁻¹)
ℤeven-is-multiple-of-two (negsucc n) en = I (even-is-multiple-of-two (succ n) en)
 where
  I : Σ k   , succ n  2 ℕ* k  Σ k   , negsucc n  pos 2 * k
  I (0      , e) = 𝟘-elim (positive-not-zero n e)
  I (succ k , e) = - pos (succ k) , II
   where
    II : negsucc n  pos 2 * (- pos (succ k))
    II = negsucc n                =⟨ refl                                                
         - pos (succ n)           =⟨ ap  z  - pos z) e                                
         - pos (2 ℕ* succ k)      =⟨ ap -_ (pos-multiplication-equiv-to-ℕ 2 (succ k) ⁻¹) 
         - pos 2 * pos (succ k)   =⟨ negation-dist-over-mult (pos 2) (pos (succ k)) ⁻¹   
         pos 2 * (- pos (succ k)) 

ℤodd-is-succ-multiple-of-two : (n : )  ℤodd n  Σ k   , n  succℤ (pos 2 * k)
ℤodd-is-succ-multiple-of-two n on = I (ℤeven-is-multiple-of-two (predℤ n) (ℤpred-odd-is-even n on))
 where
  I : Σ k   , predℤ n  pos 2 * k  Σ k   , n  succℤ (pos 2 * k)
  I (k , e) = k , II
   where
    II : n  succℤ (pos 2 * k)
    II = n                 =⟨ succpredℤ n ⁻¹ 
         succℤ (predℤ n)   =⟨ ap succℤ e     
         succℤ (pos 2 * k) 

ℤtimes-even-is-even : (m n : )  ℤeven m  ℤeven (m * n)
ℤtimes-even-is-even m n em = I (ℤeven-or-odd n)
 where
  I : ℤeven n  ℤodd n  ℤeven (m * n)
  I (inl en) = ℤeven*even m n em en
  I (inr on) = ℤeven*odd m n em on

ℤtimes-even-is-even' : (m n : )  ℤeven n  ℤeven (m * n)
ℤtimes-even-is-even' m n en = transport ℤeven (ℤ*-comm n m) (ℤtimes-even-is-even n m en)

ℤeven-transport : (z : )  (ez : ℤeven z) (p : ℤeven z  ℤodd z)  p  inl ez
ℤeven-transport z ez (inl ez') = ap inl (ℤeven-is-prop z ez' ez)
ℤeven-transport z ez (inr oz)  = 𝟘-elim (ℤeven-not-odd z ez oz)

ℤodd-transport : (z : )  (oz : ℤodd z) (p : ℤeven z  ℤodd z)  p  inr oz
ℤodd-transport z oz (inl ez)  = 𝟘-elim (ℤeven-not-odd z ez oz)
ℤodd-transport z oz (inr oz') = ap inr (ℤodd-is-prop z oz' oz)

\end{code}