-- FVIntmax/Propositions.lean

import Mathlib.Order.Bounds.Basic

import Mathlib.Order.Bounds.Defs

import Mathlib.Order.Defs

import Aesop

import FVIntmax.Wheels.Dictionary

namespace Intmax

def iso {X : Type} [Preorder X] (a b : X) := a ≤ b ∧ b ≤ a

notation:51 (priority := high) a:52 " ≅ " b:52 => iso a b

section iso

variable {X : Type} [Preorder X]
         {a b c : X}

end iso

def IsEquivRel {X : Type} [Preorder X] := ∀ a b : X, a ≤ b ↔ a ≅ b

class Setoid' (X : Type) extends Preorder X where
  isEquiv : IsEquivRel (X := X)

section Automation

variable {α : Type} [Preorder α]
         {x y : α}

end Automation

section Propositions

variable {X Y : Type}

section proposition3

variable [Preorder X]
         {x? y? join? join'? : Option X}
         {x y join join' : X}

end proposition3

section Automation

variable {X : Type} [Setoid' X]
         {x y : X}
         {x? y? : Option X}

end Automation

-- Repository definitions used:
content: notation:51 (priority := high) a:52 " ≅ " b:52 => iso a b

-- Repository lemmas used:
content: theorem List.getElem_append_left{α : Type u_1} {l₁ l₂ : List α} {i : Nat} (hn : i < l₁.length) :\n(l₁ ++ l₂)[i] = l₁[i]

-- Local definitions used:
content: def iso {X : Type} [Preorder X] (a b : X) := a ≤ b ∧ b ≤ a

content: def IsEquivRel {X : Type} [Preorder X] := ∀ a b : X, a ≤ b ↔ a ≅ b

content: class Setoid' (X : Type) extends Preorder X where
  isEquiv : IsEquivRel (X := X)

-- Local lemmas used:
content: @[simp, refl]
lemma iso_rfl : a ≅ a

content: @[trans]
lemma iso_trans : (a ≅ b) → (b ≅ c) → a ≅ c

content: lemma proposition2 [Setoid' X] {x y : X} :
  (∃ join : X, IsLUB {x, y} join) ↔ x ≅ y

content: lemma proposition2' [Setoid' X] {join x y : X} (h : IsLUB {x, y} join) :
  (x ≅ join) ∧ y ≅ join

content: lemma proposition3' : 
  (∃ join : X, IsLUB {x, y} join) ↔ (∃ join : Option X, IsLUB {.some x, .some y, .none} join)

-- Target theorem and proof:
lemma proposition4 [Setoid' X] {x y : Option X} :
  (∃ join : Option X, IsLUB {x, y, .none} join) ↔ (x ≠ .none ∧ y ≠ .none → x ≅ y)
:= by
  refine' Iff.intro (λ h ⟨h₁, h₂⟩ ↦ _) (λ h ↦ _)
  · rcases x with _ | x <;> rcases y with _ | y <;> [rfl; simp at h₁; simp at h₂; skip]
    simp
    rw [←proposition3'] at h
    rcases h with ⟨join, h⟩
    obtain ⟨h₁, h₂⟩ := proposition2' h
    exact iso_trans h₁ h₂.symm
  · rcases x with _ | x <;> rcases y with _ | y
    · use .none; simp
    · use .some y; simp
    · use .some x; simp
    · simp at h
      simp_rw [←proposition3']
      exact proposition2.2 h