module SharedWorld.Argument (
        Argument, PeerId(..), startArgument
    ) where

import SharedWorld.World ( World )

-- | An argument is a way to change your mind about the world.
data Argument w = Argument
    { argMostRecentWorld :: w
    , argOtherPeerId     :: PeerId
    }

-- Synchronization sketch:
--
--   - Both parties start in agreement; they check by exchanging checksums of their states.
--
--   - Each changes their state and sends changes to the other.
--
--   - Changes are always sent with strictly increasing consecutive sequence numbers.  The
--   counter is reset at each Resolution.
--
--   - You immediately apply your own changes, but you buffer the other side's changes.
--
--   - One of the peers is Dom, the other is Sub.
--
--   - Dom may initiate Resolution; at the end of which the two sides agree on the world.
--
--   - During Resolution: Dom sends Sub the Resolution.Start; Sub replies with
--   Resolution.Ok; each has implicitly specified the sequence number up to which to
--   resolve; each applies the other's changes in addition to their own; each check
--   agreement by exchanging checksums of the world; each resets their sequence number
--   counter; the world is locked during synchronization.
--

-- | To prevent misunderstandings, peers identify themselves when arguing.
--
-- Celine's Law: Communication can only happen between equals.
data PeerId = PeerId (String, Int)

-- | Start an argument with another peer.
startArgument :: (World w) => w -> PeerId -> IO (Argument w)
startArgument world peerId = do
    return (Argument { argMostRecentWorld = world
                     , argOtherPeerId     = peerId
                     })
