\import Data.List \hiding (Sort)
\import Data.Maybe
\import Function.Meta
\import Logic
\import Logic.Meta
\import Meta
\import Paths
\import Paths.Meta
\import Logic.Rewriting.ARS.Relation
\import Set \hiding (#)
\import Data.Fin
\import Data.Shifts
\import Data.SubList
\import Logic.Rewriting.TRS.HRS
\import Logic.Rewriting.TRS.Linearity
\import Data.Maybe
\import Logic.Rewriting.TRS.MetaContexts
\import Logic.Rewriting.TRS.Substitutions
\import Logic.Rewriting.TRS.Union
\import Logic.Rewriting.TRS.Union.Colors
\import Logic.Rewriting.TRS.Union.Confluence
\import Logic.Rewriting.TRS.Utils
\open TheoremContext

\func join-tlcrs
{tc : TheoremContext} {context : List Sort'} {s : Sort'}
(color : Color)
(A B C : PureTerm env context s)
(A~>B : Closure (TopLevelColoredReduction color {EmptyMetaContext} {context} {s}) A B)
(A~>C : Closure (TopLevelColoredReduction color {EmptyMetaContext} {context} {s}) A C)
(monochrome-confluence : ConfluentialSystem (envs color) (rules color))
: \Sigma (X : PureTerm env context s) (Closure (TopLevelColoredReduction color) B X) (Closure (TopLevelColoredReduction color) C X) =>
\let | (a, subst, eq-a, root-colors) => decompose-term color A
| inner-ms => LinearMetaContext {envs color} a
| (b, eq-b, a~>b) => iterate-decomposition (Linear.convert-to-term {envs color} a) subst B (rewrite unwrap-injection eq-a) A~>B root-colors
| (c, eq-c, a~>c) => iterate-decomposition (Linear.convert-to-term {envs color} a) subst C (rewrite unwrap-injection eq-a) A~>C root-colors
| join-b-c : StraightJoin b c (Closure (\lam x y => \Sigma (rd : monochrome-reduction color x y) (FunctionalWitness {envs color} {rules color} rd))) =>  monochrome-confluence (Linear.convert-to-term {envs color} a) b c (Closure.lift (\lam t => t) (\lam rel => rel.1) _ _ a~>b) (Closure.lift (\lam t => t) (\lam rel => rel.1) _ _ a~>c)
| injected-reduct => MetaSubstitution.apply (inject-term envs {_} {_} {inner-ms} join-b-c.common-reduct) SubList.sublist-nil-free subst
| lifted-b~>d => Closure.lift (\lam x => MetaSubstitution.apply (inject-term envs x) SubList.sublist-nil-free subst) (\lam rel => lift-relation color subst rel.1 rel.2) join-b-c.a common-reduct join-b-c.a~>cr
| lifted-c~>d => Closure.lift (\lam x => MetaSubstitution.apply (inject-term envs x) SubList.sublist-nil-free subst) (\lam rel => lift-relation color subst rel.1 rel.2) join-b-c.b common-reduct join-b-c.b~>cr
\in (injected-reduct, transport (Closure (TopLevelColoredReduction color) __ injected-reduct) eq-b lifted-b~>d, transport (Closure (TopLevelColoredReduction color) __ injected-reduct) eq-c lifted-c~>d)

\func lift-relation
{tc : TheoremContext} {context : List Sort'} {s : Sort'} {mc : MetaContext Sort'}
(color : Color)
(subst : MetaSubstitution env nil mc EmptyMetaContext)
{t u : Term (envs color) context s mc}
(t~>u : monochrome-reduction color t u)
(fw : FunctionalWitness {envs color} {rules color} t~>u)
: TopLevelColoredReduction color
(MetaSubstitution.apply (inject-term envs t) SubList.sublist-nil-free subst)
(MetaSubstitution.apply (inject-term envs u) SubList.sublist-nil-free subst)
\elim t, u, t~>u, fw
| t, u, rewrite-with-rule idx msubst msubst[l]=t msubst[r]=u, fw =>
rewrite-with-rule-colored
(produce-colored-root color t msubst subst (LinearRegistry.rule-l {rules color} idx) msubst[l]=t (LinearRegistry.rule-func-root {rules color} idx))
idx
(\lam {s1} mvar => MetaSubstitution.apply (inject-term envs (msubst mvar)) SubList.sublist-nil-free subst)
(rewrite (inv msubst[l]=t, inv (unwrap-injection _), injection-weakening-commutation color, injection-over-metasubstitution color, metacommutation) idp)
(rewrite (inv msubst[r]=u, injection-weakening-commutation color, injection-over-metasubstitution color, metacommutation) idp)
| func f-A arguments-A, func f-B arguments-B, rewrite-with-parameter-f idp index rd eq, param-rewriting fw =>
rewrite-with-parameter-f-colored idp idp index
(rewrite (trivial-sublist-contractible (SubList.extend-right-single SubList.sublist-nil-free) SubList.sublist-nil-free) (transport (\lam sl => TopLevelColoredReduction color (MetaSubstitution.apply
(inject-term envs (arguments-A index)) SubList.sublist-nil-free subst)
(MetaSubstitution.apply (inject-term envs (arguments-B index)) sl subst))
(trivial-sublist-contractible SubList.sublist-nil-free (SubList.extend-right-single SubList.sublist-nil-free) ) (lift-relation color subst rd fw)))
(\lam j _x => rewrite (eq j _x) idp)
| metavar m-A arguments-A, metavar m-B arguments-B, rewrite-with-parameter-m idp i rd eq, ()
\where {
\func produce-colored-root
{tc : TheoremContext} {context : List Sort'} (color : Color) {s : Sort'} {mc mc' mc'' : MetaContext Sort'}
(t : Term (envs color) context s mc')
(msubst : MetaSubstitution (envs color) context mc mc')
(outer-msubst : MetaSubstitution env nil mc' mc'')
(l : Term (envs color) nil s mc)
(eq : MetaSubstitution.apply {envs color} (weakening {envs color} l SubList.sublist-nil-free) SubList.identity msubst = t)
(froot : FunctionRoot {envs color} l)
: HasColoredRoot color (MetaSubstitution.apply (inject-term envs t) SubList.sublist-nil-free outer-msubst)
\elim t, l, eq
| func f arguments, func f1 arguments1, eq => func-root idp
| var index p, func f arguments, ()
| metavar m arguments, func f arguments1, ()

\lemma injection-over-metasubstitution
{tc : TheoremContext} {context context' : List Sort'} {s : Sort'} {mc mc' : MetaContext Sort'} (color : Color)
(msubst : MetaSubstitution (envs color) context' mc mc')
(t : Term (envs color) context s mc)
(sublist : SubList context' context)
: inject-term envs (MetaSubstitution.apply {envs color} t sublist msubst) = MetaSubstitution.apply (inject-term envs t) sublist (\lam m => inject-term envs (msubst m))
\elim t
| var index p => idp
| metavar m arguments =>
\let inductive : (\lam i => inject-term envs (MetaSubstitution.apply {envs color} (arguments i) sublist msubst)) = (\lam i => MetaSubstitution.apply (inject-term envs (arguments i)) sublist (\lam m => inject-term envs (msubst m))) => ext (\lam i => injection-over-metasubstitution color msubst (arguments i) sublist)
\in rewriteI inductive (rewrite (injection-over-left-extension color _ (\lam (i : Index (mc.m-domain m)) => MetaSubstitution.apply {envs color} (arguments i) sublist msubst)) (injection-over-substitution color _ (msubst m)))
| func f arguments => Term.fext (\lam index => injection-over-metasubstitution color msubst (arguments index) _)
\where {
\lemma injection-over-left-extension
{tc : TheoremContext} {context context' add-context : List Sort'} {mc : MetaContext Sort'} (color : Color)
(subst : Substitution {envs color} context context' mc)
: extend-substitution-left sublist (\lam i => inject-term envs (subst i))
=
(\lam i => inject-term envs (extend-substitution-left {envs color} sublist subst i)) => ext (
partial-fin-induction (\lam fin => extend-substitution-left sublist (\lam i => inject-term envs (subst i)) fin
=
inject-term envs (extend-substitution-left {envs color} sublist subst fin))
(\lam i1 => rewrite (extend-substitution-left.on-begin,extend-substitution-left.on-begin {envs color}) idp)
(\lam i1 => rewrite (extend-substitution-left.on-end, extend-substitution-left.on-end {envs color}) (inv (inject-term.over-transport-sort _ _)))
)

\lemma injection-over-right-extension
{tc : TheoremContext} {context context' add-context : List Sort'} {mc : MetaContext Sort'} (color : Color)
(subst : Substitution {envs color} context context' mc)
: append-context-right (\lam i => inject-term envs (subst i)) {add-context}
=
(\lam i => inject-term envs (append-context-right {envs color} subst i)) => ext (partial-fin-induction
(\lam fin => append-context-right (\lam i => inject-term envs (subst i)) fin = inject-term envs (append-context-right {envs color} subst fin))
(\lam i1 => rewrite append-context-right.on-begin (rewrite (append-context-right.on-begin {envs color}) (rewrite (weakening.over-transport-sort, weakening.over-transport-sort {envs color}, injection-weakening-commutation, inject-term.over-transport-sort _ (weakening {envs color} (subst i1) SubList.id+right)) idp)))
(\lam i1 => rewrite append-context-right.on-end (rewrite (append-context-right.on-end {envs color}) idp))
)

\lemma injection-over-substitution
{tc : TheoremContext} {context context' : List Sort'} {s : Sort'} {mc : MetaContext Sort'} (color : Color)
(subst : Substitution {envs color} context context' mc)
(t : Term (envs color) context s mc)
: inject-term envs (Substitution.apply {envs color} t subst) = Substitution.apply (inject-term envs t) (\lam i => inject-term envs (subst i)) \elim t
| var index idp => idp
| metavar m arguments => Term.mext (\lam index => injection-over-substitution color subst (arguments index))
| func f arguments => Term.fext (\lam index => injection-over-substitution color (append-context-right {envs color} subst) (arguments index) *> pmap (Substitution.apply (inject-term envs (arguments index))) (inv (injection-over-right-extension color _)))
}

\lemma metacommutation {env : FSignature} {context context' : List Sort} {s : Sort} {mc mc' mc'' : MetaContext Sort}
(msubst : MetaSubstitution env context' mc mc')
(msubst2 : MetaSubstitution env nil mc' mc'')
(t : Term env context s mc)
(sublist : SubList context' context)
:
MetaSubstitution.apply t sublist (\lam m => MetaSubstitution.apply (msubst m) SubList.sublist-nil-free msubst2)
=
MetaSubstitution.apply (MetaSubstitution.apply t sublist msubst) SubList.sublist-nil-free msubst2 \elim t
| var index p => idp
| metavar m arguments =>
\let inductive : (\lam i => MetaSubstitution.apply (arguments i) sublist
(\lam {s : env.Sort} (m : mc.metaname s) => MetaSubstitution.apply (msubst m) SubList.sublist-nil-free msubst2)) = (\lam i => MetaSubstitution.apply (MetaSubstitution.apply (arguments i) sublist msubst) SubList.sublist-nil-free msubst2) => ext (\lam i => metacommutation msubst msubst2 (arguments i) sublist)
\in rewrite inductive (rewrite (subst-extend-left-comm msubst2 sublist (\lam (i : Index (mc.m-domain m)) => MetaSubstitution.apply (arguments i) sublist msubst)) (subst-metasubst-comm msubst2 (msubst m) _))
| func f arguments => Term.fext (\lam index => rewrite (trivial-sublist-contractible (SubList.extend-right-single SubList.sublist-nil-free) SubList.sublist-nil-free) (metacommutation msubst msubst2 (arguments index) (SubList.extend-right-single sublist)))

\lemma subst-metasubst-comm
{env : FSignature} {context context' : List Sort} {s : Sort} {mc' mc'' : MetaContext Sort}
(msubst2 : MetaSubstitution env nil mc' mc'')
(t : Term env context' s mc')
(subst : Substitution context' context mc')
:
Substitution.apply (MetaSubstitution.apply t SubList.sublist-nil-free msubst2) (\lam i => MetaSubstitution.apply (subst i) SubList.sublist-nil-free msubst2)
=
MetaSubstitution.apply (Substitution.apply t subst) SubList.sublist-nil-free msubst2 \elim t
| var index idp => idp
| metavar m arguments =>
\let inductive-ext : (\lam i => MetaSubstitution.apply (Substitution.apply (arguments i) subst) SubList.sublist-nil-free msubst2) =
(\lam i => Substitution.apply (MetaSubstitution.apply (arguments i) SubList.sublist-nil-free msubst2) (\lam i => MetaSubstitution.apply (subst i) SubList.sublist-nil-free msubst2))
=> ext (\lam i => inv (subst-metasubst-comm msubst2 (arguments i) subst))
\in rewrite (inductive-ext, subst-comm) idp
| func f arguments => Term.fext (\lam index =>
rewrite (trivial-sublist-contractible _ SubList.sublist-nil-free, trivial-sublist-contractible (SubList.extend-right-single SubList.sublist-nil-free), inv (subst-metasubst-comm _ (arguments index) _), append-context-right-inside-metaapply) idp)

\lemma append-context-right-inside-metaapply
{env : FSignature} {context context' add-context : List Sort} {mc' mc'' : MetaContext Sort}
(subst : Substitution context context' mc')
(msubst : MetaSubstitution env nil mc' mc'')
: append-context-right (\lam i => MetaSubstitution.apply (subst i) SubList.sublist-nil-free msubst) {add-context} = (\lam index => MetaSubstitution.apply (append-context-right subst index) SubList.sublist-nil-free msubst) => ext (
partial-fin-induction
(\lam fin => append-context-right (\lam i => MetaSubstitution.apply (subst i) SubList.sublist-nil-free msubst) {add-context} fin = MetaSubstitution.apply (append-context-right subst fin) SubList.sublist-nil-free msubst)
(\lam fin => repeat {2} (rewrite append-context-right.on-begin) (rewrite (weakening.over-transport-sort, weakening.over-transport-sort, MetaSubstitution.over-transport-sort, weakening.over-metasubstitution) idp))
(\lam fin => repeat {2} (rewrite append-context-right.on-end) idp))

\lemma subst-extend-left-comm {env : FSignature} {context context' add-context : List Sort} {mc' mc'' : MetaContext Sort}
(msubst2 : MetaSubstitution env nil mc' mc'')
(sublist : SubList context' context)
(subst : Substitution add-context context mc')
: extend-substitution-left
sublist (\lam (i : Index add-context) => MetaSubstitution.apply (subst i) SubList.sublist-nil-free msubst2) = (\lam index => MetaSubstitution.apply (extend-substitution-left sublist subst index) SubList.sublist-nil-free msubst2) => ext (
partial-fin-induction
(\lam fin => extend-substitution-left
sublist (\lam (i : Index add-context) => MetaSubstitution.apply (subst i) SubList.sublist-nil-free msubst2) fin = MetaSubstitution.apply (extend-substitution-left sublist subst fin) SubList.sublist-nil-free msubst2)
(\lam fin => repeat {2} (rewrite extend-substitution-left.on-begin) idp)
(\lam fin => repeat {2} (rewrite extend-substitution-left.on-end) (rewriteI MetaSubstitution.over-transport-sort idp)))
}

\func decompose-term {tc : TheoremContext} {context : List Sort'} {s : Sort'}
(color : Color)
(A : PureTerm env context s) :
\Sigma (t : LinearTerm (envs color) context s)
(subst : MetaSubstitution env nil (LinearMetaContext {envs color} t) EmptyMetaContext)
(MetaSubstitution.apply (convert-to-injected-term color t) SubList.sublist-nil-free subst = A)
(\Pi {s : Sort'} (m : metaname {LinearMetaContext {envs color} t} s) -> HasExcludedColoredRoot color (subst m)) \elim A
| var index p => (lt-var {envs color} index p,
impossible-lambda,
cases color idp,
impossible-lambda)
| metavar () arguments
| func f arguments => \case \elim color, decideEq f.1 color \with {
| _, yes idp =>
\let | inner-decompositions i => decompose-term f.1 (arguments i)
| context-producer i => LinearMetaContext {envs f.1} (inner-decompositions i).1
| unified-meta-context => ModularMetaContext context-producer
| unified-substitution : MetaSubstitution env nil unified-meta-context EmptyMetaContext => \lam m => (inner-decompositions m.1).2 m.2
\in (l-func f.2 (\lam i => (inner-decompositions i).1),
unified-substitution,
Term.fext (\lam index =>
rewrite (trivial-sublist-contractible (SubList.extend-right-single SubList.sublist-nil-free) SubList.sublist-nil-free) idp *>
inv (modular-commutation (\lam i => LinearMetaContext {envs f.1} (inner-decompositions i).1) index SubList.sublist-nil-free (convert-to-injected-term f.1 (inner-decompositions index).1) unified-substitution) *>
(inner-decompositions index).3),
\lam m => (inner-decompositions m.1).4 m.2)
| color, no n =>
(l-full-metavar {envs color},
\lam mvar => transport (PureTerm env context __) (inv mvar) (func f arguments),
Term.fext (\lam index => rewrite (append-context-right.to-identity, plain-identity-effect) idp),
\lam {s1} m => \case \elim s1, \elim m \with {
| s1, idp => ex-func-root n
})
}

\func decompose-along-reduction {tc : TheoremContext} {context : List Sort'} {s : Sort'} {inner-mc mc : MetaContext Sort'}
(color : Color)
(t : Term (envs color) context s inner-mc)
(B : Term env context s mc)
(subst : MetaSubstitution env nil inner-mc mc)
(root-colors : \Pi {s : Sort'} (m : inner-mc.metaname s) -> HasExcludedColoredRoot color (subst m))
(A~>B : TopLevelColoredReduction color {mc} {context} {s} (MetaSubstitution.apply (inject-term envs t) SubList.sublist-nil-free subst) B)
: \Sigma (u : Term (envs color) context s inner-mc)
(MetaSubstitution.apply (inject-term envs u) SubList.sublist-nil-free subst = B)
(rd : monochrome-reduction color t u)
(FunctionalWitness {envs color} {rules color} rd) \elim t, B, A~>B
| func f arguments, func (color',f') arguments', rewrite-with-parameter-f-colored inlf=inlf' p1 i tlcr eq => \case \elim color', decideEq color color', \elim f', \elim arguments', \elim inlf=inlf', \elim tlcr, \elim eq \with {
| _, yes idp, f', arguments', inlf=inlf', tlcr, eq =>
\let | f=f' => sigma-set-equalizer inlf=inlf'
| eq-p : inlf=inlf' = pmap (later (color,__)) f=f' => prop-pi
\in inductive _ _ f=f' arguments arguments' subst root-colors i (rewriteI eq-p tlcr) (rewriteI eq-p eq)
| color', no n, f', arguments', inlf=inlf', tlcr, eq => absurd (n (pmap __.1 inlf=inlf'))
}
| func f arguments, B, rewrite-with-rule-colored hcr idx big-subst l[bs]=injt r[bs]=B =>
\let | (middle-subst, substitution-equality, l-eq) =>
decompose-metasubstitution
color (get-rule-pattern {_} {_} {color} idx) (transport (Term (envs color) __ s inner-mc) (inv ++_nil) (func {envs color} f arguments)) big-subst subst
(rewrite (inv Transports.extension-to-nil-left, Transports.extension-to-nil-right, inject-term.over-transport-ctx _ (func f arguments)) (metasubst-over-transport-2 ++_nil
(inject-term envs (Linear.convert-to-term {envs color} (get-rule-pattern {_} {_} {color} idx)))
(func (color,f) (\lam i => inject-term envs (arguments i))) big-subst subst (rewrite (unwrap-injection {_} {color}) l[bs]=injt)))
root-colors
| term-u => MetaSubstitution.apply {envs color} (weakening {envs color} (rule-right-linear {_} {_} {color} idx) SubList.sublist-nil-free) SubList.identity middle-subst
| colored-coherence => colored-metacomposition color middle-subst subst big-subst substitution-equality SubList.identity (weakening {envs color} (rule-right-linear {_} {_} {color} idx) SubList.sublist-nil-free)
\in (term-u,
inv colored-coherence *> pmap (MetaSubstitution.apply __ SubList.identity big-subst) (inv (injection-weakening-commutation color _ _)) *> r[bs]=B,
produce-monochrome-reduction color idx middle-subst (func f arguments) term-u
(rewrite (different-weakening {envs color}) (metasubst-over-transport {envs color} ++_nil _ (func f arguments) middle-subst
(rewrite (inv Transports.extension-to-nil-right)
(pmap (\lam sl => MetaSubstitution.apply {envs color} (weakening {envs color} (Linear.convert-to-term {envs color} (get-rule-pattern {_} {_} {color} idx)) sl) (SubList.extend-right-single SubList.identity) middle-subst)
Transports.extension-to-nil-left) *> l-eq)))
idp (rewriteI (unwrap-injection {_} {color}) (JRegistry.rule-func-root (color,idx))),
rule-rewriting {envs color})
| metavar m arguments, B, A~>B =>
\let
| other-root-color => root-colors m
| root-color => TopLevelColoredReduction.extract-root-coloring A~>B
| empty : Empty => eliminate-colors color other-root-color root-color
| var index p, B, A~>B => \let rc => TopLevelColoredReduction.extract-root-coloring A~>B \in \case \elim rc
\where {
\func inductive {tc : TheoremContext} {context : List Sort'} {s : Sort'} {inner-mc mc : MetaContext Sort'} {color : Color}
(f f' : symbol {envs color} s)
(eq : f = f')
(arguments :
\Pi (index : Index (domain {envs color} f)) ->
Term (envs color) (context ++ f FSignature.!!domain {envs color} index) (f FSignature.!!sort {envs color} index) inner-mc)
(arguments' :
\Pi (index : Index (domain (color,f'))) ->
Term env (context ++ (color,f') env.!!domain index) ((color,f') env.!!sort index) mc)
(subst : MetaSubstitution env nil inner-mc mc)
(root-colors : \Pi {s : Sort'} (m : inner-mc.metaname s) -> HasExcludedColoredRoot color (subst m))
(i : Index (domain (color,f)))
(tlcr : TopLevelColoredReduction color (MetaSubstitution.apply
(inject-term envs (arguments i)) (SubList.extend-right-single SubList.sublist-nil-free)
subst) (arguments-over-f (pmap (later (color,__)) eq) arguments' i))
(eq' :
\Pi (j : Index (domain (color,f))) -> (j = i -> Empty) -> MetaSubstitution.apply
(inject-term envs (arguments j)) (SubList.extend-right-single SubList.sublist-nil-free)
subst = arguments-over-f (pmap (later (color,__)) eq) arguments' j)
:  \Sigma (u : Term (envs color) context s inner-mc)
(MetaSubstitution.apply (inject-term envs u) SubList.sublist-nil-free subst = func (color,f') arguments')
(rd : monochrome-reduction color (func f arguments) u)
(FunctionalWitness {envs color} {rules color} rd)\elim eq
| idp => \let inductive-step => decompose-along-reduction color (arguments i) (arguments' i) subst root-colors (rewrite trivial-sublist-contractible tlcr) \in
(func f (pointed-function arguments i inductive-step.1),
Term.fext
(\lam index => pointed-induction
(\lam j fx => MetaSubstitution.apply (inject-term envs fx) (SubList.extend-right-single SubList.sublist-nil-free) subst = arguments' j)
arguments
i
inductive-step.1
(rewrite trivial-sublist-contractible inductive-step.2)
(\lam j n => eq' j n)
index),
rewrite-with-parameter-f idp i (rewrite pointed-function.at-index inductive-step.3) (\lam j _x => inv (pointed-function.not-at-index arguments _ _ j _x)),
param-rewriting (unifying-lemma _ _ _ _ _ inductive-step.4))
\where {
\func unifying-lemma {tc : TheoremContext} {context : List Sort'} {s : Sort'} {mc : MetaContext Sort'} {color : Color}
(t u v : Term (envs color) context s mc) (eq : v = u) (rd : RewriteRelation {envs color} (rules color) t u)
(fw : FunctionalWitness {envs color} {rules color} rd):
FunctionalWitness {envs color} {rules color} (transportInv (RewriteRelation {envs color} (rules color) t) eq rd) \elim eq | idp => fw
}

\lemma eliminate-colors {tc : TheoremContext} (color : Color) {context context' : List Sort'} {s : Sort'} {msig : MetaContext Sort'}
{T : Term env context s msig} {subst : Substitution context context' msig}
(hcr : HasExcludedColoredRoot color T)
(hcr' : HasColoredRoot color (Substitution.apply T subst))
: Empty \elim T, hcr, hcr'
| func f arguments, ex-func-root p, func-root q => p q

\lemma different-weakening {env : FSignature} {context : List Sort} {s : Sort} {ms : MetaContext Sort}
(T : Term env nil s ms)
: weakening T (SubList.sublist-nil-free {_} {context}) =
transport (Term env __ s ms) ++_nil (weakening T (SubList.extend-right-single SubList.identity)) \elim context
| nil => idp
| :: a context => lemma ++_nil (sublist-skip SubList.sublist-nil-free) (sublist-skip SubList.sublist-nil-free) (trivial-sublist-contractible _ _) T
\where {
\lemma lemma  {env : FSignature} {context context' : List Sort} {s : Sort} {ms : MetaContext Sort}
(eq : context' = context) (sl : SubList nil context) (sl' : SubList nil context') (sl=sl' : sl = transport (SubList nil) eq sl') (T : Term env nil s ms) :
weakening T sl = transport (Term env __ s ms) eq (weakening T sl') \elim context, eq, sl=sl'
| nil, idp, idp => idp
| :: a context, idp, idp => idp
}

\lemma metasubst-over-transport {env : FSignature} {context context' : List Sort} {s : Sort} {ms ms' : MetaContext Sort} (eq : context = context')
(T : Term env context s ms) (S : Term env context' s ms') (msubst : MetaSubstitution env context' ms ms')
(eq' : MetaSubstitution.apply T (transport (SubList context') (inv eq) SubList.identity) msubst = transport (Term env __ s ms') (inv eq) S)
: MetaSubstitution.apply (transport (Term env __ s ms) eq T) SubList.identity msubst = S \elim eq
| idp => eq'

\lemma metasubst-over-transport-2 {env : FSignature} {context context' : List Sort} {s : Sort} {ms ms' ms'' : MetaContext Sort}
(eq : context' = context)
(T : Term env nil s ms) (S : Term env context s ms'')
(msubst : MetaSubstitution env context ms ms')
(msubst2 : MetaSubstitution env nil ms'' ms')
(eq' : MetaSubstitution.apply (weakening T SubList.sublist-nil-free) SubList.identity msubst = MetaSubstitution.apply S SubList.sublist-nil-free msubst2)
: MetaSubstitution.apply (weakening T SubList.sublist-nil-free) (transport (SubList context) (inv eq) SubList.identity) msubst = MetaSubstitution.apply (transport (Term env __ s ms'') (inv eq) S) SubList.sublist-nil-free msubst2 \elim eq
| idp => eq'
}

\func produce-monochrome-reduction
{tc : TheoremContext} {context : List Sort'} {s : Sort'} {mc : MetaContext Sort'} (color : Color)
(idx : rule-J {rules color} s)
(subst : MetaSubstitution (envs color) context (rule-linear-mc idx) mc)
(l r : Term (envs color) context s mc)
(l-eq : MetaSubstitution.apply {envs color} (weakening {envs color} (Linear.convert-to-term {envs color} (get-rule-pattern idx)) SubList.sublist-nil-free) SubList.identity subst = l)
(r-eq : MetaSubstitution.apply {envs color} (weakening {envs color} (rule-right-linear idx) SubList.sublist-nil-free) SubList.identity subst = r)
(l-is-func : FunctionRoot (convert-to-injected-term color (get-rule-pattern idx)))
: monochrome-reduction color l r => rewrite-with-rule idx subst l-eq r-eq

\lemma colored-metacomposition {tc : TheoremContext} {global-context : List Sort'} {ms-a ms-b ms-c : MetaContext Sort'}
(color : Color)
(subst-a : MetaSubstitution (envs color) global-context ms-a ms-b)
(subst-b : MetaSubstitution env nil ms-b ms-c)
(subst-c : MetaSubstitution env global-context ms-a ms-c)
(eq : \Pi {s : Sort'} (m : ms-a.metaname s) -> subst-c m = MetaSubstitution.apply (inject-term envs (subst-a m)) SubList.sublist-nil-free subst-b)
{context : List Sort'} {s : Sort'}
(sublist : SubList global-context context)
(t : Term (envs color) context s ms-a)
: MetaSubstitution.apply (inject-term envs t) sublist subst-c = MetaSubstitution.apply (inject-term envs (MetaSubstitution.apply {envs color} t sublist subst-a)) SubList.sublist-nil-free subst-b \elim t
| var index p => idp
| metavar m arguments =>
\let | inner i : MetaSubstitution.apply (inject-term envs (arguments i)) sublist subst-c = MetaSubstitution.apply (inject-term envs (MetaSubstitution.apply {envs color} (arguments i) sublist subst-a)) SubList.sublist-nil-free subst-b => colored-metacomposition color subst-a subst-b subst-c eq sublist (arguments i)
| inner-ext : (\lam i => MetaSubstitution.apply (inject-term envs (arguments i)) sublist subst-c) = (\lam i => MetaSubstitution.apply (inject-term envs (MetaSubstitution.apply {envs color} (arguments i) sublist subst-a)) SubList.sublist-nil-free subst-b) => ext inner
\in rewrite (eq m) (inv (rewrite inner-ext (rewrite (injection-over-substitution color) (commutation subst-b (\lam ind => inject-term envs (extend-substitution-left {envs color} sublist (\lam i => MetaSubstitution.apply {envs color} (arguments i) sublist subst-a) ind)) (inject-term envs (subst-a m)) *> pmap (Substitution.apply (MetaSubstitution.apply (inject-term envs (subst-a m)) SubList.sublist-nil-free subst-b)) (extend-left-commutation color _ _ _)))))
| func f arguments => Term.fext (\lam index => colored-metacomposition color subst-a subst-b subst-c eq (SubList.extend-right-single sublist) (arguments index) *> invariant-through-empty-subst subst-b SubList.sublist-nil-free (SubList.extend-right-single SubList.sublist-nil-free) _)
\where {
\lemma extend-left-commutation {tc : TheoremContext} {context-a context-b context-c : List Sort'} {mc mc' : MetaContext Sort'}
(color : Color)
(subst : Substitution {envs color} context-b context-c mc)
(sublist : SubList context-a context-c)
(msubst : MetaSubstitution env nil mc mc') :
(\lam i => MetaSubstitution.apply (inject-term envs (extend-substitution-left {envs color} sublist subst i))
SubList.sublist-nil-free msubst) = extend-substitution-left sublist (\lam (j : Index context-b) => MetaSubstitution.apply
(inject-term envs (subst j)) SubList.sublist-nil-free msubst) => ext (
partial-fin-induction (\lam fin => MetaSubstitution.apply (inject-term envs (extend-substitution-left {envs color} sublist subst fin))
SubList.sublist-nil-free msubst = extend-substitution-left sublist (\lam (j : Index context-b) => MetaSubstitution.apply
(inject-term envs (subst j)) SubList.sublist-nil-free msubst) fin)
(\lam i1 => rewrite (extend-substitution-left.on-begin, extend-substitution-left.on-begin {envs color}) idp)
(\lam i1 => rewrite (extend-substitution-left.on-end, extend-substitution-left.on-end {envs color}, inject-term.over-transport-sort _ (subst i1), MetaSubstitution.over-transport-sort) idp)
)

\lemma commutation {tc : TheoremContext} {term-context context : List Sort'} {s : Sort'} {ms-a ms-b : MetaContext Sort'}
(metasubst : MetaSubstitution env nil ms-a ms-b)
(subst : Substitution term-context context ms-a)
(T : Term env term-context s ms-a)
:
MetaSubstitution.apply (Substitution.apply T subst) SubList.sublist-nil-free metasubst =
Substitution.apply
(MetaSubstitution.apply T SubList.sublist-nil-free metasubst)
(\lam i => MetaSubstitution.apply (subst i) SubList.sublist-nil-free metasubst) \elim T
| var index idp => idp
| metavar m arguments => rewrite subst-comm (pmap (Substitution.apply (metasubst m)) (ext (\lam index => commutation metasubst subst (arguments index))))
| func f arguments => Term.fext (\lam index => (rewrite (trivial-sublist-contractible _ SubList.sublist-nil-free)) (commutation metasubst (append-context-right subst) (arguments index) *> rewrite (trivial-sublist-contractible (SubList.extend-right-single SubList.sublist-nil-free) SubList.sublist-nil-free) (pmap (Substitution.apply (MetaSubstitution.apply (arguments index) SubList.sublist-nil-free metasubst)) (append-context-right-commutation subst metasubst))))
\where {
\lemma append-context-right-commutation {env : FSignature} {context-a context-b context-c : List Sort} {ms ms' : MetaContext Sort}
(subst : Substitution context-a context-c ms)
(metasubst : MetaSubstitution env nil ms ms')
: (\lam i => MetaSubstitution.apply (append-context-right subst {context-b} i) SubList.sublist-nil-free metasubst) =
append-context-right (\lam (i : Index context-a) => MetaSubstitution.apply (subst i) SubList.sublist-nil-free metasubst) => ext (
partial-fin-induction
(\lam ind => MetaSubstitution.apply (append-context-right subst ind) SubList.sublist-nil-free metasubst =
append-context-right
(\lam (i : Index context-a) => MetaSubstitution.apply (subst i) SubList.sublist-nil-free metasubst) ind)
(\lam i1 => rewrite (append-context-right.on-begin, append-context-right.on-begin, inv (MetaSubstitution.over-transport-sort _ (subst i1) _ _), weakening.over-metasubstitution) idp)
(\lam i1 => repeat {2} (rewrite append-context-right.on-end) idp)
)
}

\lemma injection-over-substitution
{tc : TheoremContext} {context context' : List Sort'} {s : Sort'} {ms : MetaContext Sort'}
(color : Color)
(t : Term (envs color) context s ms) (subst : Substitution {envs color} context context' ms)
: inject-term envs (Substitution.apply {envs color} t subst) = Substitution.apply (inject-term envs t) (\lam i => inject-term envs (subst i)) \elim t
| var index p => \case \elim s, \elim p \with {
| s, idp => idp
}
| metavar m arguments => Term.mext (\lam index => injection-over-substitution color (arguments index) subst)
| func f arguments => Term.fext (\lam index => rewrite (push-append-context-right color subst) (injection-over-substitution color (arguments index) (append-context-right {envs color} subst)))
\where {
\lemma push-append-context-right {tc : TheoremContext} {context context' additional-context : List Sort'} {ms : MetaContext Sort'}
(color : Color)
(subst : Substitution {envs color} context context' ms)
: append-context-right (\lam i => inject-term envs (subst i)) {additional-context} =
(\lam i => inject-term envs (append-context-right {envs color} subst i)) =>
ext (push-append-context-right-ext color subst)

\lemma push-append-context-right-ext {tc : TheoremContext}
(color : Color)
{context context' additional-context : List Sort'} {ms : MetaContext Sort'}
(subst : Substitution {envs color} context context' ms) (index : Index (context ++ additional-context))
: append-context-right (\lam i => inject-term envs (subst i)) {additional-context}  index =
inject-term envs (append-context-right {envs color} subst index) \elim context, index
| nil, index => idp
| :: a context, 0 => injection-weakening-commutation color (SubList.extend-right-single SubList.identity) _
| :: a additional-context, suc index => push-append-context-right-ext color (\lam i => subst (suc i)) index
}
}

\lemma injection-weakening-commutation
{tc : TheoremContext} (color : Color) {context context' : List Sort'} {ms : MetaContext Sort'} {s : Sort'}
(sublist : SubList context context')
(t : Term (envs color) context s ms)
: weakening (inject-term envs t) sublist = inject-term envs (weakening {envs color} t sublist) \elim t
| var index p => idp
| metavar m arguments => Term.mext (\lam index => injection-weakening-commutation color sublist (arguments index))
| func f arguments => Term.fext (\lam index => injection-weakening-commutation color (SubList.extend-right-both sublist) (arguments index))

\func decompose-metasubstitution
{tc : TheoremContext} {pattern-context core-context : List Sort'} {s : Sort'} {inner-mc mc : MetaContext Sort'}
(color : Color)
(l : LinearPattern (envs color) pattern-context s)
(t : Term (envs color) (core-context ++ pattern-context) s inner-mc)
(big-substitution : MetaSubstitution env core-context (LinearMetaContext {envs color} l) mc)
(middle-substitution : MetaSubstitution env nil inner-mc mc)
(eq :
MetaSubstitution.apply
(weakening (inject-term envs (Linear.convert-to-term {envs color} l)) (SubList.extend-left-single SubList.identity {core-context}))
(SubList.extend-right-single SubList.identity) big-substitution =
MetaSubstitution.apply
(inject-term envs t)
SubList.sublist-nil-free
middle-substitution)
(root-colors : \Pi {s : Sort'} (m : inner-mc.metaname s) -> HasExcludedColoredRoot color (middle-substitution m))
: \Sigma (inner-substitution : MetaSubstitution (envs color) core-context (LinearMetaContext {envs color} l) inner-mc)
(\Pi {s : Sort'} (m : metaname {LinearMetaContext {envs color} l} s) ->
big-substitution m = MetaSubstitution.apply (inject-term envs (inner-substitution m)) SubList.sublist-nil-free middle-substitution)
(MetaSubstitution.apply {envs color} (weakening {envs color} (Linear.convert-to-term {envs color} l) (SubList.extend-left-single SubList.identity {core-context})) (SubList.extend-right-single SubList.identity) inner-substitution = t)
\elim l, t
| l-func f arguments, metavar m arguments1 =>
\let | opposite-color-for-m => root-colors m
| colored-root-for-f : HasColoredRoot color (func (color,f)
(\lam i => MetaSubstitution.apply (weakening (inject-term envs (ModularMetaContext.upgrade-metavariables {envs color}
(\lam i => LinearMetaContext {envs color} (arguments i)) (Linear.convert-to-term {envs color} (arguments i))))
(SubList.extend-right-both (SubList.extend-left-single SubList.identity {core-context}))) (SubList.extend-right-single (SubList.extend-right-single SubList.identity)) big-substitution)) => func-root idp
| colored-root-for-m : HasColoredRoot color (Substitution.apply (middle-substitution m) (extend-substitution-left SubList.sublist-nil-free
(\lam i => MetaSubstitution.apply (inject-term envs (arguments1 i)) SubList.sublist-nil-free middle-substitution))) => rewriteI eq colored-root-for-f
\in contradiction {decompose-along-reduction.eliminate-colors color opposite-color-for-m colored-root-for-m}
| l-func f arguments, func f1 arguments1 =>
\let f-eq : f = f1 => sigma-set-equalizer (pmap (unfunc (color,f)) eq)
\in inductive-step color f f1 f-eq arguments arguments1 big-substitution middle-substitution root-colors eq
| l-full-metavar, t =>
(\lam {s1} mvar => transport (\lam sort => Term (envs color) (core-context ++ pattern-context) sort inner-mc) (inv mvar) t,
\lam {s1} m => \case \elim s, \elim t, \elim big-substitution, \elim eq, \elim m \with {
| s, t, big-substitution, eq, idp =>
rewrite {1} (inv (plain-identity-effect (big-substitution idp))) (pmap (Substitution.apply (big-substitution idp)) (inv weakening-extension-ext)) *> eq
},
unfold transport (transport (\lam sbst => Substitution.apply {envs color} t sbst = t) (inv (weakening-extension-ext {envs color} {core-context} {pattern-context} {inner-mc})) (plain-identity-effect {envs color} _)))
| l-var index p (), t
\where {
\func unfunc {env : FSignature} {context : List Sort} {s : Sort} {ms : MetaContext Sort} (f : symbol s)
(T : Term env context s ms) : symbol s \elim T
| var index p => f
| metavar m arguments => f
| func f1 arguments => f1

\func inductive-step
{tc : TheoremContext} {pattern-context core-context : List Sort'} {s : Sort'} {inner-mc mc : MetaContext Sort'}
(color : Color)
(f : symbol {envs color} s)
(f1 : symbol {envs color} s)
(eq : f = f1)
(arguments : DArray {FSignature.arity {envs color} f}
(\lam index => LinearPattern (envs color) (pattern-context ++ f FSignature.!!domain {envs color} index) (f FSignature.!!sort {envs color} index)))
(arguments1 :
\Pi (index : Index (domain {envs color} f1)) ->
Term (envs color) ((core-context ++ pattern-context) ++ f1 FSignature.!!domain {envs color} index) (f1 FSignature.!!sort {envs color} index)
inner-mc)
(big-substitution : MetaSubstitution env core-context (LinearMetaContext {envs color} (l-func f arguments)) mc)
(middle-substitution : MetaSubstitution env nil inner-mc mc)
(root-colors : \Pi {s : Sort'} (m : inner-mc.metaname s) -> HasExcludedColoredRoot color (middle-substitution m))
(eq' : MetaSubstitution.apply
(weakening (inject-term envs (Linear.convert-to-term {envs color} (l-func {envs color} f arguments))) (SubList.extend-left-single SubList.identity {core-context}))
(SubList.extend-right-single SubList.identity) big-substitution =
MetaSubstitution.apply
(inject-term envs (func {envs color} f1 arguments1))
SubList.sublist-nil-free
middle-substitution):
\Sigma (inner-substitution : MetaSubstitution (envs color) core-context (LinearMetaContext {envs color} (l-func f arguments)) inner-mc)
(\Pi {s : Sort'} (m : metaname {LinearMetaContext {envs color} (l-func f arguments)} s) ->
big-substitution m = MetaSubstitution.apply (inject-term envs (inner-substitution m)) SubList.sublist-nil-free middle-substitution)
(MetaSubstitution.apply {envs color} (weakening {envs color} (Linear.convert-to-term {envs color} (l-func f arguments)) (SubList.extend-left-single SubList.identity {core-context})) (SubList.extend-right-single SubList.identity) inner-substitution = func f1 arguments1)
\elim eq
| idp =>
\have | sigmas-or => pmap unwrap-func eq'
| z => pmap (unjust {\Sigma (f : symbol s) (\Pi (index : Index (domain f)) ->
Term env ((core-context ++ pattern-context) ++ f env.!!domain index) (f env.!!sort index)
mc)} ((color,f), \lam i => MetaSubstitution.apply
(inject-term envs (arguments1 i)) (SubList.extend-right-single SubList.sublist-nil-free)
middle-substitution)) sigmas-or
| res => sigma-set-equalizer z
| args-eq i => pmap (__ i) res
| inductive i => decompose-metasubstitution color
(arguments i)
(transport (Term (envs color) __ _ inner-mc) (++-assoc {_} {core-context} {pattern-context} {f1 FSignature.!!domain {envs color} i}) (arguments1 i))
(\lam m => big-substitution (i, m))
middle-substitution
(rewrite
(apply-modularity,
inv (unwrap-injection.swap _ _ (Linear.convert-to-term {envs color} (arguments i))),
Transports.lb-ls-to-ls.inv',
Transports.rs-rs-to-rs.inv',
Transports.nil-to-right-nil)
(ad-hoc-lemma (Linear.convert-to-term {envs color} (arguments i)) ++-assoc (args-eq i))
)
root-colors
\in (\lam {s1} mvar => (inductive mvar.1).1 mvar.2,
\lam {s1} m => (inductive m.1).2 m.2,
Term.fext {envs color} (\lam index =>
\have ind => (inductive index).3
\in rewrite (inv (apply-modularity {envs color}
(\lam i => LinearMetaContext {envs color} (arguments i))
(\lam i => (inductive i).1)
(SubList.extend-right-single (SubList.extend-right-single SubList.identity))
(SubList.extend-right-both (SubList.extend-left-single SubList.identity))
(Linear.convert-to-term {envs color} (arguments index))))
(rewrite Transports.lb-ls-to-ls
(rewrite Transports.rs-rs-to-rs
(expand-substitution-3 {envs color} _ _ _ _ _ _ ind)))))

{tc : TheoremContext} {subst-context context big-context big-context' : List Sort'} {s : Sort'} {ms-a ms-b : MetaContext Sort'}
{n : Nat} {index : Fin n}
{color : Color}
{producer : Fin n -> MetaContext Sort'}
(term : Term (envs color) context s (producer index))
(eq : big-context = big-context')
{sublist : SubList context big-context}
{sublist' : SubList subst-context big-context}
{msubst : MetaSubstitution env subst-context (ModularMetaContext producer) ms-b}
{S : Term (envs color) big-context s ms-a}
{msubst' : MetaSubstitution env nil ms-a ms-b}
{sublist'' : SubList nil big-context}
(target-eq : MetaSubstitution.apply (weakening (inject-term envs (ModularMetaContext.upgrade-metavariables {envs color} producer term)) sublist) sublist' msubst = MetaSubstitution.apply (inject-term envs S) sublist'' msubst')
: MetaSubstitution.apply (weakening (inject-term envs (ModularMetaContext.upgrade-metavariables {envs color} producer term)) (transport (SubList context) eq sublist)) (transport (SubList subst-context) eq sublist') msubst = MetaSubstitution.apply (inject-term envs (transport (Term (envs color) __ s ms-a) eq S)) (transport (SubList nil) eq sublist'') msubst' \elim eq
| idp => target-eq
}

\lemma weakening-extension-ext {env : FSignature} {left-context right-context : List Sort} {mc : MetaContext Sort}
: extend-substitution-left {_} {left-context} {right-context} (SubList.extend-right-single SubList.identity) (\lam i => weakening (var i idp) (SubList.extend-left-single SubList.identity)) = plain-identity {_} {_} {mc} =>
ext (partial-fin-induction
(\lam i =>
extend-substitution-left (SubList.extend-right-single SubList.identity) (\lam i => weakening (var i idp) (SubList.extend-left-single SubList.identity)) i
=
plain-identity {_} {_} {mc} i)
(\lam i1 =>
\let | q => extend-substitution-left.on-begin (SubList.extend-right-single SubList.identity) (\lam i => weakening (var i idp) (SubList.extend-left-single SubList.identity)) i1
\in q *> var-extensionality (Shifts.over-right-single _))
(\lam i1 =>
\let | q => extend-substitution-left.on-end (SubList.extend-right-single SubList.identity) (\lam i => weakening (var i idp) (SubList.extend-left-single SubList.identity)) i1
| big-eq => Shifts.left-extension {Sort} {left-context} {right-context} i1
\in q *> rewrite (pmap sigma-to-var big-eq) (rewrite transport-var-over-sort (var-extensionality idp))))

\lemma expand-substitution-3 {env : FSignature} {term-context ms-context big-context big-context' : List Sort} {s : Sort} {ms ms' : MetaContext Sort}
(T : Term env term-context s ms)
(msubst : MetaSubstitution env ms-context ms ms')
(sublist : SubList term-context big-context)
(sublist' : SubList ms-context big-context)
(S : Term env big-context' s ms')
(eq : big-context' = big-context)
(target : MetaSubstitution.apply (weakening T sublist) sublist' msubst = transport (Term env __ s ms') eq S)
: MetaSubstitution.apply (weakening T (transport (SubList term-context) (inv eq) sublist)) (transport (SubList ms-context) (inv eq) sublist') msubst = S \elim eq
| idp => target