\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}
