import Mathlib.Tactic
import Mathlib.Topology.Instances.Irrational

/-!
Self-contained slice for Chapter 11.8 (partial), providing just enough to state
PiecewiseConstantOn.RS_integ_sub.
-/

namespace Chapter11

open Classical

/-- Bounded intervals (from Section 11.1). -/
inductive BoundedInterval where
  | Ioo (a b:ℝ) : BoundedInterval
  | Icc (a b:ℝ) : BoundedInterval
  | Ioc (a b:ℝ) : BoundedInterval
  | Ico (a b:ℝ) : BoundedInterval

open BoundedInterval

/-- Coercion to a set of real numbers. -/
@[coe]
def BoundedInterval.toSet (I: BoundedInterval) : Set ℝ := match I with
  | Ioo a b => .Ioo a b
  | Icc a b => .Icc a b
  | Ioc a b => .Ioc a b
  | Ico a b => .Ico a b

instance BoundedInterval.inst_coeSet : Coe BoundedInterval (Set ℝ) where
  coe := toSet

instance BoundedInterval.instEmpty : EmptyCollection BoundedInterval where
  emptyCollection := Ioo 0 0

@[simp]
theorem BoundedInterval.coe_empty : ((∅ : BoundedInterval):Set ℝ) = ∅ := by
  simp [toSet]

@[simp]
theorem BoundedInterval.set_Ioo (a b:ℝ) : (Ioo a b : Set ℝ) = .Ioo a b := by rfl

@[simp]
theorem BoundedInterval.set_Icc (a b:ℝ) : (Icc a b : Set ℝ) = .Icc a b := by rfl

@[simp]
theorem BoundedInterval.set_Ioc (a b:ℝ) : (Ioc a b : Set ℝ) = .Ioc a b := by rfl

@[simp]
theorem BoundedInterval.set_Ico (a b:ℝ) : (Ico a b : Set ℝ) = .Ico a b := by rfl

instance BoundedInterval.instMembership : Membership ℝ BoundedInterval where
  mem I x := x ∈ (I:Set ℝ)

@[simp]
theorem BoundedInterval.mem_iff (I: BoundedInterval) (x:ℝ) :
  x ∈ I ↔ x ∈ (I:Set ℝ) := by rfl

instance BoundedInterval.instSubset : HasSubset BoundedInterval where
  Subset I J := ∀ x, x ∈ I → x ∈ J

@[simp]
theorem BoundedInterval.subset_iff (I J: BoundedInterval) :
  I ⊆ J ↔ (I:Set ℝ) ⊆ (J:Set ℝ) := by rfl

/-- Constant and ConstantOn (from Section 11.8). -/
abbrev Constant {X Y : Type} (f : X → Y) : Prop :=
  ∃ c, ∀ x, f x = c

abbrev ConstantOn (f : ℝ → ℝ) (X : Set ℝ) : Prop :=
  Constant (fun x : X ↦ f ↑x)

/-- `constant_value` and `constant_value_on` (from Section 11.8). -/
noncomputable abbrev constant_value {X Y : Type} [hY : Nonempty Y] (f : X → Y) : Y :=
  if h : Constant f then h.choose else hY.some

noncomputable abbrev constant_value_on (f : ℝ → ℝ) (X : Set ℝ) : ℝ :=
  constant_value (fun x : X ↦ f ↑x)

/-- Right and left limits (from Section 11.8). -/
noncomputable abbrev right_lim (f: ℝ → ℝ) (x₀:ℝ) : ℝ :=
  lim ((nhdsWithin x₀ (.Ioi x₀)).map f)

noncomputable abbrev left_lim (f: ℝ → ℝ) (x₀:ℝ) : ℝ :=
  lim ((nhdsWithin x₀ (.Iio x₀)).map f)

/-- α-length (from Section 11.8). -/
noncomputable abbrev α_length (α: ℝ → ℝ) (I: BoundedInterval) : ℝ := match I with
| Icc a b => if a ≤ b then (right_lim α b) - (left_lim α a) else 0
| Ico a b => if a ≤ b then (left_lim α b) - (left_lim α a) else 0
| Ioc a b => if a ≤ b then (right_lim α b) - (right_lim α a) else 0
| Ioo a b => if a < b then (left_lim α b) - (right_lim α a) else 0

notation3:max α"["I"]ₗ" => α_length α I

/-- Partitions (from Section 11.1). -/
@[ext]
structure Partition (I : BoundedInterval) where
  intervals : Finset BoundedInterval
  exists_unique (x : ℝ) (hx : x ∈ I) : ∃! J, J ∈ intervals ∧ x ∈ J
  contains (J : BoundedInterval) (hJ : J ∈ intervals) : J ⊆ I

instance Partition.instMembership (I : BoundedInterval) : Membership BoundedInterval (Partition I) where
  mem P J := J ∈ P.intervals

/-- Piecewise constant (with a given partition) and on an interval (from Section 11.8). -/
abbrev PiecewiseConstantWith (f : ℝ → ℝ) {I : BoundedInterval} (P : Partition I) : Prop :=
  ∀ J ∈ P, ConstantOn f (J : Set ℝ)

abbrev PiecewiseConstantOn (f : ℝ → ℝ) (I : BoundedInterval) : Prop :=
  ∃ P : Partition I, PiecewiseConstantWith f P

/-- Piecewise-constant RS integral over a partition (from Section 11.8). -/
noncomputable abbrev PiecewiseConstantWith.RS_integ (f:ℝ → ℝ) {I: BoundedInterval} (P: Partition I) (α: ℝ → ℝ)   :
  ℝ := ∑ J ∈ P.intervals, constant_value_on f (J:Set ℝ) * α[J]ₗ

/-- Piecewise-constant RS integral on an interval (from Section 11.8). -/
noncomputable abbrev PiecewiseConstantOn.RS_integ (f:ℝ → ℝ) (I: BoundedInterval) (α:ℝ → ℝ):
  ℝ := if h: PiecewiseConstantOn f I then PiecewiseConstantWith.RS_integ f h.choose α else 0

/-- Theorem 11.8.8 (c) (Laws of RS integration) / Exercise 11.8.8 -/
theorem PiecewiseConstantOn.RS_integ_sub {f g: ℝ → ℝ} {I: BoundedInterval}
  {α:ℝ → ℝ} (hα: Monotone α)
  (hf: PiecewiseConstantOn f I) (hg: PiecewiseConstantOn g I) :
  RS_integ (f - g) I α = RS_integ f I α - RS_integ g I α := by
end Chapter11