{-# OPTIONS --guardedness #-}
open import Agda.Builtin.Equality
open import Data.Product
open import Data.Sum
open import Level
open import Relation.Unary using (_β_)
module is-lib.InfSys.FlexCoinduction {π} where
  private
    variable
      U : Set π
  
  open import is-lib.InfSys.Base {π}
  open import is-lib.InfSys.Induction {π}
  open import is-lib.InfSys.Coinduction {π}
  open MetaRule
  open IS
  
  FCoIndβ¦_,_β§ : β{πc πp πn πn'} β (I : IS {πc} {πp} {πn} U) β (C : IS {πc} {πp} {πn'} U) β U β Set _
  FCoIndβ¦ I , C β§ = CoIndβ¦ I β Indβ¦ I βͺ C β§ β§
  
  bdc-lem : β{πc πp πn π' π''} 
      β (I : IS {πc} {πp} {πn} U)
      β (S : U β Set π') 
      β (Q : U β Set π'')
      β S β Q
      β S β ISF[ I ] S
      β S β ISF[ I β Q ] S
  bdc-lem _ _ _ bd cn Su with cn Su
  ... | rn , c , refl , pr = rn , (c , bd Su) , refl , pr
  bounded-coind[_,_] : β{πc πp πn πn' π'} 
      β (I : IS {πc} {πp} {πn} U) 
      β (C : IS {πc} {πp} {πn'} U)
      β (S : U β Set π')                   
      β S β Indβ¦ I βͺ C β§      
      β S β ISF[ I ] S        
      β S β FCoIndβ¦ I , C β§
  bounded-coind[ I , C ] S bd cn Su = coind[ I β Indβ¦ I βͺ C β§ ] S (bdc-lem I S Indβ¦ I βͺ C β§ bd cn) Su
  
  fcoind-to-ind : β{πc πp πn πn'}
      {is : IS {πc} {πp} {πn} U}{cois : IS {πc} {πp} {πn'} U} 
      β FCoIndβ¦ is , cois β§ β Indβ¦ is βͺ cois β§
  fcoind-to-ind co with CoIndβ¦_β§.unfold co
  ... | _ , (_ , sd) , refl , _ = sd
  
  apply-fcoind : β{πc πp πn πn'}
      {is : IS {πc} {πp} {πn} U}{cois : IS {πc} {πp} {πn'} U}
      β (rn : is .Names) β RClosed (is .rules rn) FCoIndβ¦ is , cois β§
  apply-fcoind rn c pr = apply-coind rn (c , apply-ind (injβ rn) c Ξ» i β fcoind-to-ind (pr i)) pr
  
  
  fcoind-postfix : β{πc πp πn πn'}
      {is : IS {πc} {πp} {πn} U}{cois : IS {πc} {πp} {πn'} U}
      β FCoIndβ¦ is , cois β§ β ISF[ is ] FCoIndβ¦ is , cois β§
  fcoind-postfix FCoInd with FCoInd .CoIndβ¦_β§.unfold
  ... | rn , (c , _) , refl , pr = rn , c , refl , pr
  fcoind-prefix : β{πc πp πn πn'}
      {is : IS {πc} {πp} {πn} U}{cois : IS {πc} {πp} {πn'} U}
      β ISF[ is ] FCoIndβ¦ is , cois β§ β FCoIndβ¦ is , cois β§
  fcoind-prefix (rn , c , refl , pr) = apply-fcoind rn c pr