local localCine = {}
function localCine.New(name, go)
  local instance = {}
  instance.name = name
  instance.root = go
  instance.slaves = {}
  instance.master = {}
  instance.puppeteers = {}
  setmetatable(instance, localCine)
  return instance
end
localCine.__index = {
  AddSlave = function(cine, actor, move)
    table.insert(cine.slaves, {a = actor, m = move})
  end,
  SetMaster = function(cine, actor, move)
    cine.master = {a = actor, m = move}
  end,
  AddPuppeteer = function(cine, actor, puppet)
    if cine.puppeteers[actor] == nil then
      cine.numpuppeteers = cine.numpuppeteers + 1
    end
    cine.puppeteers[actor] = puppet
  end,
  RemovePuppeteer = function(cine, actor)
    if cine.puppeteers[actor] ~= nil then
      cine.puppeteers[actor] = nil
      cine.numpuppeteers = cine.numpuppeteers - 1
    end
  end,
  Start = function(cine)
    cine.puppeteers = {}
    cine.numpuppeteers = 0
    local master = game.Puppeteer.NewForce(cine.root, cine.name, cine.master.a)
    local paramtable = {}
    cine:AddPuppeteer(master.Puppet, master)
    for _, s in ipairs(cine.slaves) do
      local cur = game.Puppeteer.NewForce(cine.root, cine.name, s.a)
      cur:AcceptSync()
      cur:SetStageName("Slave Accept Sync")
      cur:OnComplete(function(pup)
        pup:SetStageName("Slave Ending")
        cine:RemovePuppeteer(pup.Puppet)
        cine:CheckComplete()
      end)
      cine:AddPuppeteer(cur.Puppet, cur)
      table.insert(paramtable, {
        Slave = cur,
        Branch = s.m
      })
    end
    master:Sync(cine.master.m, true, paramtable)
    master:SetStageName("Master Create Sync")
    master:OnComplete(function(pup)
      pup:SetStageName("Master Ending")
      cine:RemovePuppeteer(pup.Puppet)
      cine:CheckComplete()
    end)
  end,
  CheckComplete = function(cine)
    if cine.callback ~= nil and cine.numpuppeteers < 1 then
      cine.callback(cine)
    end
  end,
  OnComplete = function(cine, cb)
    cine.callback = cb
  end
}
return localCine
