import Mathlib
import Analysis.Section_2_2
import Analysis.Tags.Section_2_2

namespace Chapter2

-- <CONTEXT>
inductive Nat where
| zero : Nat
| succ : Nat → Nat
deriving Repr, DecidableEq

instance Nat.instZero : Zero Nat := ⟨ zero ⟩

postfix:100 "++" => Nat.succ

instance Nat.instOfNat {n:_root_.Nat} : OfNat Nat n where
  ofNat := _root_.Nat.rec 0 (fun _ n ↦ n++) n

instance Nat.instOne : One Nat := ⟨ 1 ⟩

abbrev Nat.recurse (f: Nat → Nat → Nat) (c: Nat) : Nat → Nat := fun n ↦ match n with
| 0 => c
| n++ => f n (recurse f c n)

abbrev Nat.add (n m : Nat) : Nat := Nat.recurse (fun _ sum ↦ sum++) m n

instance Nat.instAdd : Add Nat where
  add := add

theorem Nat.zero_add (m: Nat) : 0 + m = m := by
  sorry

lemma Nat.add_zero (n:Nat) : n + 0 = n := by
  sorry

theorem Nat.add_comm (n m:Nat) : n + m = m + n := by
  sorry

theorem Nat.add_assoc (a b c:Nat) : (a + b) + c = a + (b + c) := by
  sorry

instance Nat.addCommMonoid : AddCommMonoid Nat where
  add_assoc := add_assoc
  add_comm := add_comm
  zero_add := zero_add
  add_zero := add_zero
  nsmul := nsmulRec

def Nat.IsPos (n:Nat) : Prop := n ≠ 0

instance Nat.instLE : LE Nat where
  le n m := ∃ a:Nat, m = n + a

instance Nat.instLT : LT Nat where
  lt n m := n ≤ m ∧ n ≠ m

theorem Nat.ge_refl (a:Nat) : a ≥ a := by
  sorry

theorem Nat.ge_trans {a b c:Nat} (hab: a ≥ b) (hbc: b ≥ c) : a ≥ c := by
  sorry

theorem Nat.ge_antisymm {a b:Nat} (hab: a ≥ b) (hba: b ≥ a) : a = b := by
  sorry

def Nat.decLe : (a b : Nat) → Decidable (a ≤ b)
  | 0, b => by
    apply isTrue
    sorry
  | a++, b => by
    cases decLe a b with
    | isTrue h =>
      cases decEq a b with
      | isTrue h =>
        apply isFalse
        sorry
      | isFalse h =>
        apply isTrue
        sorry
    | isFalse h =>
      apply isFalse
      sorry

instance Nat.decidableRel : DecidableRel (· ≤ · : Nat → Nat → Prop) := Nat.decLe

instance Nat.instLinearOrder : LinearOrder Nat where
  le_refl := ge_refl
  le_trans a b c hab hbc := ge_trans hbc hab
  lt_iff_le_not_ge a b := by
    sorry
  le_antisymm a b hab hba := ge_antisymm hba hab
  le_total a b := by
    sorry
  toDecidableLE := decidableRel

theorem Nat.add_le_add_right (a b c:Nat) : a ≤ b ↔ a + c ≤ b + c := by
  sorry

instance Nat.isOrderedAddMonoid : IsOrderedAddMonoid Nat where
  add_le_add_left a b hab c := (Nat.add_le_add_right a b c).mp hab

abbrev Nat.mul (n m : Nat) : Nat := Nat.recurse (fun _ prod ↦ prod + m) 0 n

instance Nat.instMul : Mul Nat where
  mul := mul

theorem Nat.zero_mul (m: Nat) : 0 * m = 0 := by
  sorry

theorem Nat.succ_mul (n m: Nat) : (n++) * m = n * m + m := by
  sorry

theorem Nat.one_mul' (m: Nat) : 1 * m = 0 + m := by
  sorry

theorem Nat.one_mul (m: Nat) : 1 * m = m := by
  sorry

theorem Nat.two_mul (m: Nat) : 2 * m = 0 + m + m := by
  sorry

lemma Nat.mul_zero (n: Nat) : n * 0 = 0 := by
  sorry

lemma Nat.mul_succ (n m:Nat) : n * m++ = n * m + n := by
  sorry

lemma Nat.mul_comm (n m: Nat) : n * m = m * n := by
  sorry

theorem Nat.mul_one (m: Nat) : m * 1 = m := by
  sorry

lemma Nat.pos_mul_pos {n m: Nat} (h₁: n.IsPos) (h₂: m.IsPos) : (n * m).IsPos := by
  sorry

theorem Nat.mul_add (a b c: Nat) : a * (b + c) = a * b + a * c := by
  sorry

theorem Nat.add_mul (a b c: Nat) : (a + b)*c = a*c + b*c := by
  sorry

theorem Nat.mul_assoc (a b c: Nat) : (a * b) * c = a * (b * c) := by
  sorry

instance Nat.instCommSemiring : CommSemiring Nat where
  left_distrib := mul_add
  right_distrib := add_mul
  zero_mul := zero_mul
  mul_zero := mul_zero
  mul_assoc := mul_assoc
  one_mul := one_mul
  mul_one := mul_one
  mul_comm := mul_comm

theorem Nat.mul_lt_mul_of_pos_right {a b c: Nat} (h: a < b) (hc: c.IsPos) : a * c < b * c := by
  sorry

theorem Nat.mul_gt_mul_of_pos_right {a b c: Nat} (h: a > b) (hc: c.IsPos) :
    a * c > b * c := by
  sorry

theorem Nat.mul_lt_mul_of_pos_left {a b c: Nat} (h: a < b) (hc: c.IsPos) : c * a < c * b := by
  sorry

theorem Nat.mul_gt_mul_of_pos_left {a b c: Nat} (h: a > b) (hc: c.IsPos) :
    c * a > c * b := by
  sorry

lemma Nat.mul_cancel_right {a b c: Nat} (h: a * c = b * c) (hc: c.IsPos) : a = b := by
  sorry

instance Nat.isOrderedRing : IsOrderedRing Nat where
  zero_le_one := by sorry
  mul_le_mul_of_nonneg_left := by sorry
  mul_le_mul_of_nonneg_right := by sorry
-- </CONTEXT>
-- <TARGET_THEOREM>
theorem Nat.exists_div_mod (n:Nat) {q: Nat} (hq: q.IsPos) :
    ∃ m r: Nat, 0 ≤ r ∧ r < q ∧ n = m * q + r := by
-- </TARGET_THEOREM>

end Chapter2