--

data Tree:: Nat ~> *0 ~> *0 where
  Leaf1 :: a -> Tree Z a
  Leaf2 :: a -> a -> Tree Z a
  Node1 :: Tree n a -> a -> Tree n a -> Tree (S n) a
  Node2 :: Tree n a -> a -> Tree n a -> a -> Tree n a -> Tree (S n) a

data BadTree :: Nat ~> *0 ~> *0 where
 Leaf3 :: a -> a -> a -> BadTree Z a
 Node3 :: Tree n a -> a -> Tree n a -> a -> Tree n a -> a -> Tree n a -> BadTree (S n) a

joinL:: BadTree n a -> a -> Tree n a -> Tree (S n) a
joinL (Leaf3 s m l) p x = Node2 (Leaf1 s) m (Leaf1 l) p x
-- ?
joinL (Node3 a s b m c l d) p e = Node2 (Node1 a s b) m (Node1 c l d) p e
-- ?



joinR:: Tree n a -> a -> BadTree n a -> Tree (S n) a
joinR x p (Leaf3 s m l) = Node2 x p (Leaf1 s) m (Leaf1 l)
-- ?
joinR a p (Node3 b s c m d l e) = Node2 a p (Node1 b s c) m (Node1 d l e)
-- ?

insert:: a -> Tree n a -> (Tree n a + BadTree n a)
insert x (Leaf1 y) =
  case compare x y of
    LT -> L (Leaf2 x y)
    GT -> L (Leaf2 y x)
    EQ -> L (Leaf1 y)
insert x (Leaf2 y z) =
  case (compare x y,compare x z) of
    (LT,_) ->  R (Leaf3 x y z)
    (_,GT) ->  R (Leaf3 y z x)
    (GT,LT) -> R (Leaf3 y x z)
    (_,EQ) ->  L (Leaf2 y z)
    (EQ,_) ->  L (Leaf2 y z)
insert x (Node1 t1 y t2) =
  case compare x y of
    LT -> case insert x t1 of
            L t3 -> L (Node1 t3 y t2)
            R t3 -> L (joinL t3 y t2)
    GT -> case insert x t2 of
            L t3 -> L (Node1 t1 y t3)
            R t3 -> L (joinR t1 y t3)
    EQ -> L (Node1 t1 x t2)
insert x (Node2 t1 y t2 z t3) =
  case (compare x y,compare x z) of
    (LT,_) ->  case insert x t1 of
                 L t4 -> L(Node2 t4 y t2 z t3)
                 R (Leaf3 a b c) -> R(Node3 (Leaf1 a) b (Leaf1 c) y t2 z t3)
                 R (Node3 t4 a t5 b t6 c t7) ->
                      R(Node3 (Node1 t4 a t5) b (Node1 t6 c t7) y t2 z t3)
    (_,GT) ->  case insert x t3 of
                 L t4 -> L(Node2 t1 y t2 z t4)
                 R (Leaf3 a b c) -> R(Node3 t1 y t2 z (Leaf1 a) b (Leaf1 c))
                 R (Node3 t4 a t5 b t6 c t7) ->
                      R(Node3 t1 y t2 z (Node1 t4 a t5) b (Node1 t6 c t7))
    (GT,LT) -> case insert x t2 of
                 L t4 -> L(Node2 t1 y t4 z t3)
                 R (Leaf3 a b c) -> R(Node3 t1 y (Leaf1 a) b (Leaf1 c) z t3)
                 R (Node3 t4 a t5 b t6 c t7) ->
                      R(Node3 t1 y (Node1 t4 a t5) b (Node1 t6 c t7) z t3)
    (_,EQ) ->  L (Node2 t1 y t2 z t3)
    (EQ,_) ->  L (Node2 t1 y t2 z t3)

insertTree:: a -> Tree n a -> (Tree n a + Tree (S n) a)
insertTree a t =
  case insert a t of
    L x -> L x
    R (Leaf3 a b c) -> R(Node1 (Leaf1 a) b (Leaf1 c))
    R (Node3 a small b medium c large d) -> R(Node1 (Node1 a small b) medium (Node1 c large d))
-- ?

--