package senseiTests.domainsTest;

import sensei.middleware.gms.*;
import sensei.middleware.domains.*;
import senseiTests.middleware.domainsTest.AddColourMessage;
import senseiTests.middleware.domainsTest.RemColourMessage;
import senseiTests.middleware.domainsTest.ColourPhaseCoordination;
import senseiTests.middleware.domainsTest.ColourState;
import senseiTests.middleware.domainsTest.Factory;

class ColoursSubgroupStateHandler extends StateHandlerBaseImpl implements ColoursSubgroup
{
  public ColoursSubgroupStateHandler(DomainGroupHandler groupHandler, ColoursSubgroupUser user,
      Factory factory, StateTransferAnswerer answerer) throws Exception
  {
    this.user=user;
    this.answerer=answerer;
    this.factory=factory;
    state=new StateKeeper();
    this.groupHandler=groupHandler;
  }

  public void setIdentity(int identity)
  {
    id=identity;
  }

  public void setState(String substates[])
  {
    state.setState(substates);
    user.changedState(id, state.toString());
  }

  public String getAColour()
  {
    return state.generateRandomSubState();
  }

  public void addColour(String colour) throws Exception
  {
    groupHandler.syncCastDomainMessage(factory.createAddColourMessage(id,colour), true);
  }

  public void remColour() throws Exception
  {
    groupHandler.syncCastDomainMessage(factory.createRemColourMessage(id), true);
  }

  public int getId()
  {
    return id;
  }

  public String getColour(int pos)
  {
    return state.getSubState(pos);
  }

  public void regenerateState()
  {
    state.generateRandomState();
    user.changedState(id, state.toString());
  }

  public void assumeState()
  {
    state.generateRandomState();
    answerer.onAssumeState(this);
    user.changedState(id, state.toString());
  }

  public void syncTransfer(int coordinator, PhaseCoordinationHolder p)
  {
    ColourPhaseCoordination phase = (ColourPhaseCoordination) (p.value);
    int number = phase==null? 0 : phase.nextPhase;
    PhaseAnswer answer = answerer.onSyncTranfer(this, coordinator, number);
    if (phase==null)
      p.value=factory.createCoordinationPhase(answer.phase,answer.phase,0,answer.finished);
    else
    {
      phase=factory.createCoordinationPhase(phase.phase, phase.nextPhase, phase.numPhases, phase.transferFinished);
      answer.convert(phase);
      p.value=phase;
    }
  }

  public void interruptTransfer(PhaseCoordinationHolder p)
  {
    ColourPhaseCoordination phaseC = (ColourPhaseCoordination) (p.value);
    ColourPhaseCoordination phase=
      factory.createCoordinationPhase(phaseC.phase, phaseC.nextPhase, phaseC.numPhases, phaseC.transferFinished);
    answerer.onInterruptTransfer(this, phase.nextPhase).convert(phase);
    p.value=phase;
  }

  public void continueTransfer(int[] joining_members, PhaseCoordinationHolder coordPhase, PhaseCoordination joining)
  {
    ColourPhaseCoordination phaseC = (ColourPhaseCoordination) (coordPhase.value);
    ColourPhaseCoordination phase=
      factory.createCoordinationPhase(phaseC.phase, phaseC.nextPhase, phaseC.numPhases, phaseC.transferFinished);
    answerer.onContinueTransfer(this, joining_members[0], phase.nextPhase,
      ((ColourPhaseCoordination)joining).nextPhase, state.getNumberOfSubStates()).convert(phase);
    coordPhase.value=phase;
  }

  public void startTransfer(int[] joining_members, PhaseCoordinationHolder p)
  {
    ColourPhaseCoordination phaseC = (ColourPhaseCoordination) (p.value);
    ColourPhaseCoordination phase=
      factory.createCoordinationPhase(phaseC.phase, phaseC.nextPhase, phaseC.numPhases, phaseC.transferFinished);
    answerer.onStartTransfer(this, joining_members[0], phase.nextPhase, state.getNumberOfSubStates()).convert(phase);
    p.value=phase;
  }

  public State getState(PhaseCoordinationHolder p)
  {
    ColourPhaseCoordination phaseC = (ColourPhaseCoordination) (p.value);
    ColourPhaseCoordination phase=
      factory.createCoordinationPhase(phaseC.phase, phaseC.nextPhase, phaseC.numPhases, phaseC.transferFinished);
    int states=state.getNumberOfSubStates();
    PhaseAnswer answer = answerer.onGetState(this, phase.nextPhase, states);
    answer.convert(phase, states, true);
    p.value=phase;
    return factory.createState(state.getSubState(answer.phase));
  }

  public void setState(State s, PhaseCoordination p)
  {
    ColourPhaseCoordination phase = (ColourPhaseCoordination) p;
    ColourState state = (ColourState)s;
    this.state.setSubState(state.chain, phase.phase, phase.numPhases);
    user.changedState(id, this.state.toString());
    answerer.onSetState(this, state.chain, phase.phase);
  }

  public void stopTransfer(int[] joining_members, boolean transferFinished)
  {
    if (transferFinished && !state.isValidatedState())
      state.validateState();
    answerer.onStopTransfer(this, joining_members[0], transferFinished);
  }


  public void processPTPMessage(int sender, Message msg)
  {
    System.out.println("processPTPMessage");
  }
  public void processCastMessage(int sender, Message msg)
  {
    boolean ok;
    if (msg instanceof AddColourMessage)
    {
      AddColourMessage message = (AddColourMessage) msg;
      state.addSubState(message.colour);
      ok=true;
    }
    else if (msg instanceof RemColourMessage)
      ok = state.removeSubState();
    else
      ok=false;
    if (ok)
      user.changedState(id, state.toString());
  }

  public void memberAccepted(int identity, GroupHandler handler, View theView)
  {
    this.groupHandler = (DomainGroupHandler) (handler);
  }
  public void changingView()
  {
  }
  public void installView(View theView)
  {
  }
  public void excludedFromGroup()
  {
  }

  StateKeeper state;
  boolean onTransfer;
  int id;

  DomainGroupHandler groupHandler;
  ColoursSubgroupUser user;
  StateTransferAnswerer answerer;
  Factory factory;
};