package uk.co.patrickhaston.mars;
import java.awt.Color;
import java.util.Vector;
//import javax.swing.JPanel;
//import javax.swing.JScrollPane;
import java.awt.Rectangle;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.*;
//import javax.swing.JList;
//import java.awt.Graphics;

// The MarsConversation class displays a conversation between
// the user and a character in the game.
// The user selects statements from a list of choices
// and the character gives responses.
// A possible future option is to allow multiple characters
// to join the conversation.
//
// Version 0.901
// Issues from 14 Sept 2004
// - doesn't display unless the frame is resized.  Fixed 2 Oct 2004
// - need to track the flow of conversation
// - need to display list of activities (as a vector?)  Fixed 2 Oct 2004
// - need to display list of available constructions (as a vector?)  Fixed 2 Oct 2004
// - need to display list of available research (as a vector?)  Fixed 2 Oct 2004
//
// Version 0.904
// updated 8 Feb 2005
// - layout changed to fit in a horizontal area below the map
//
// Version 0.906
// updated 10 June 2005
// - view of person added

public class MarsConversation extends MPanel 
{
  public MPanel speechPanel = null;
  // This is the area of the screen for the conversation
  public MScrollPane speechScrollPane = null;
  // This allows the conversation to scroll
  public MList speechList = null;
  // This contains the record of what has been said during the conversation
  public MPanel statementPanel = null;
  // This is the area of the screen for picking a new statement
  public MList statementList = null;
  // This contains a list of statements to pick
  public MScrollPane statementScrollPane = null;
  // This allows the statement list to scroll
  public MarsStatements conversation;
  // An array of things said that makes up the record of the conversation
  public MarsMyStatements myStatements;
  // A subset of the full list of statements showing only what can
  // be selected by the user at this point in time.
  public MarsFrame theFrame;
  // A conversation is between two people - in this case it is between
  // the user (Person #1 in the Poeple array) and the selected
  // individual:
  public int personId;
  public MarsPerson person;
  public int agreedAction;
  // The action that has been agreed
  public static int ACTION_NONE = 0;
  public static int ACTION_START_ACTIVITY = 1;
  public static int ACTION_STOP_ACTIVITY = 2;
  public static int ACTION_SEND_REPORT = 3;
  
  public int agreedActivity;
  // the new activity type that has been agreed
  
  public int agreedActivitySpecial;
  // eg the type of construction or the technology to research
  
  public MarsPersonFacePanel facePanel = null;
  // a view of the person's face
  
  public MPanel faces = null;
  
  public int lastSpeaker = 1;
  
  public Vector listOfFaces = null;
  
  public int status;
  public static int INTRODUCTIONS = 1;
  public static int READY = 2;
  public static int PROPOSAL_MADE = 3;
  public static int GOODBYES = 4;
  
  public MarsConversation(MarsFrame f)
  {
    try
    {
      theFrame = f;
      jbInit();
    }
    catch(Exception e)
    {
      e.printStackTrace();
    }
  }

  private void jbInit() throws Exception
  {
    this.setLayout(new BorderLayout());
    // Create the components
    int w = theFrame.getWidth() - 110;
    int h = theFrame.getHeight() - 100;
    this.setPreferredSize(new Dimension(w, h));
    speechPanel = new MPanel();
    speechScrollPane = new MScrollPane();
    speechList = new MList();
    statementPanel = new MPanel();
    statementList = new MList();
    statementScrollPane = new MScrollPane();

    conversation = new MarsStatements();
    myStatements = new MarsMyStatements();

    speechScrollPane.getViewport().add(speechList, null);
    speechScrollPane.setBounds(new Rectangle(0, 0, (w/2), h - 120));
    speechPanel.add(speechScrollPane);
    speechList.setListData(conversation);
    speechPanel.setPreferredSize(new Dimension((w/2), h - 120));
    speechScrollPane.setPreferredSize(new Dimension((w/2), h - 120));
    //speechPanel.setBackground(Color.darkGray);
    speechList.setBackground(Color.darkGray);

    statementScrollPane.getViewport().add(statementList, null);
    statementScrollPane.setBounds(new Rectangle(0, 0, (w/2), h - 120));
    statementPanel.add(statementScrollPane);
//    statementList.setListData(theFrame.mars.MyStatements);
    statementList.setListData(myStatements);
    statementPanel.setPreferredSize(new Dimension((w/2), h - 120));
    statementScrollPane.setPreferredSize(new Dimension((w/2), h - 120));
    statementList.setBackground(Color.gray);
    
    faces = new MPanel();
    faces.setPreferredSize(new Dimension(w, 120));

    MouseListener mouseListener = new MouseAdapter() 
    {
      public void mouseClicked(MouseEvent e) 
      {
        if (e.getClickCount() == 2) 
        {
          int index = statementList.locationToIndex(e.getPoint());
          if (index >= 0)
          {
            String theText = ((MarsMyStatement) myStatements.elementAt(index)).theText;
            // add the statement to the record of the conversation
            speak(1, theText);
            // record the selection made
            userChoice(index);
            // Respond to the statement made by the user
            response(index);
            // update the view of the conversation
            speechList.setListData(conversation);
          }
        }
      }
    };
    statementList.addMouseListener(mouseListener);

    // Assemble the panels
    this.add(faces, BorderLayout.NORTH);
    this.add(speechPanel, BorderLayout.EAST);
    this.add(statementPanel, BorderLayout.WEST);

    theFrame.mars.logEvent("Conversation Panels created.");
    theFrame.mars.logEvent("faces Panels size: w=" + faces.getWidth() + " h=" + faces.getHeight());
    theFrame.mars.logEvent("Conversation Panels assembled.");
    
    setStatements(1);
    agreedAction = ACTION_NONE;
    agreedActivity = -1;
    agreedActivitySpecial = -1;
    
    listOfFaces = new Vector();
    
    status = INTRODUCTIONS;
  }

  public void setStatements(int choice)
  {
    myStatements.clear();
    if (theFrame == null) return;
    if (theFrame.mars == null) return;
    if (theFrame.mars.MyStatements == null) return;
    if (theFrame.mars.MyStatements.size() < 1) return;
    if (choice == 0) // the conversation has ended
    {
      // The following statement is hard-coded in.
      // it needs to check to make sure the person said yes
      // it also should call a function in MarsModel called StartNewActivity which handles all
      // the assignments of people and resources.
      if (agreedAction == ACTION_START_ACTIVITY)
      {
        theFrame.mars.Activities.startNewActivity(agreedActivity, agreedActivitySpecial, personId, 1);
      }
      theFrame.stopConversation();
      return;
    }
    
    MarsMyStatement s = new MarsMyStatement(0);
    
    if (((MarsChoice) theFrame.mars.Choices.elementAt(choice)).useStatements)
    {
      for (int i=1; i<theFrame.mars.MyStatements.size(); i++)
      {
        s = new MarsMyStatement((MarsMyStatement)
          theFrame.mars.MyStatements.elementAt(i));
        if(s.choice == choice)
        {
          myStatements.addElement(s);
        }
      }
    }
    else
    {
      // now work out how to build the statement list
      switch (choice)
      {
        case 2: // Type of information that the player wants to know
          s = new MarsMyStatement(0);
          s.choice = 0;
          s.response = "Update";
          s.theText = "What are you doing?";
          myStatements.addElement(s);
          s = new MarsMyStatement(0);
          s.choice = 0;
          s.response = "activityUpdate";
          s.theText = "Give me an update on your current task?";
          myStatements.addElement(s);
          agreedAction = ACTION_SEND_REPORT;
          break;
        case 3: // Action to be taken
          for (int i=1; i<theFrame.mars.ActivityTypes.size(); i++)
          {
            s = new MarsMyStatement(0);
            s.choice = 0;
            s.response = "newActivity";
            s.theText = "I want you to start a new " 
              + ((MarsType) theFrame.mars.ActivityTypes.elementAt(i)).getName()
              + " task.";
            myStatements.addElement(s);
            agreedAction = ACTION_START_ACTIVITY;
          }
          break;
        case 6: // Activity Special 
          if (agreedActivity == 1)
          {
            // Type of construction
            for (int i=1; i<theFrame.mars.ConstructionTypes.size(); i++)
            {
              s = new MarsMyStatement(0);
              s.choice = 0;
              s.response = "newConstruction";
              s.theText = "I want you to start making a new " 
                + ((MarsConstructionType) theFrame.mars.ConstructionTypes.elementAt(i)).getName()
                + ".";
              s.setSpecial(i);
              myStatements.addElement(s);
            }
          }
          if (agreedActivity == 2)
          {
            // Type of research
            for (int i=1; i<theFrame.mars.Technologies.size(); i++)
            {
              s = new MarsMyStatement(0);
              s.choice = 0;
              s.response = "newResearch";
              s.theText = "I want you to start researching " 
                + ((MarsTechnology) theFrame.mars.Technologies.elementAt(i)).name
                + ".";
              s.setSpecial(i);
              myStatements.addElement(s);
            }
          }
          break;
/*        caselse: // error trapping
          MarsMyStatement s = new MarsMyStatement();
          s.choice = 0;
          s.response = "";
          s.theText = "My comms unit has a glitch, I'll reset it and call you back.";
          myStatements.addElement(s);
          break;*/
      }
    }
     // update the view of the conversation
    speechList.setListData(conversation);
    // update the statements
    statementList.setListData(myStatements);
  }

  public void clear()
  {
    this.removeAll();
    faces.removeAll();
    conversation.clear();
    agreedAction = ACTION_NONE;
    agreedActivity = -1;
    agreedActivitySpecial = -1;
    status = INTRODUCTIONS;
  }

  public void setPerson(int p)
  { 
    personId = p;
    person = new MarsPerson((MarsPerson) theFrame.mars.People.elementAt(personId));
    agreedAction = ACTION_NONE;
    agreedActivity = -1;
    agreedActivitySpecial = -1;
    
    // Create a panel for the player
    facePanel = new MarsPersonFacePanel(theFrame.mars, 1);
    
    // Add the facePanel to the faces panel
    faces.add(facePanel, BorderLayout.CENTER);
    
    // Add their face to the list
    listOfFaces.add(facePanel);

    // Create a panel to show their face
    facePanel = new MarsPersonFacePanel(theFrame.mars, p);
    //facePanel.setPreferredSize(new Dimension(64, 100));

    // Add the facePanel to the faces panel
    faces.add(facePanel, BorderLayout.CENTER);
    
    // Add their face to the list
    listOfFaces.add(facePanel);

    // Assemble the panels
    this.add(faces, BorderLayout.NORTH);
    this.add(speechPanel, BorderLayout.WEST);
    this.add(statementPanel, BorderLayout.EAST);

    theFrame.mars.logEvent("Conversation Panels created.");
    theFrame.mars.logEvent("faces Panels size: w=" + faces.getWidth() + " h=" + faces.getHeight());
    theFrame.mars.logEvent("Conversation Panels assembled.");
    
    // Make the person say hello.
    MarsResponse r = theFrame.mars.Responses.selectResponse("Hi", personId);
    if(r != null)
    {
      // update the conversation
      conversation.addStatement(person.getName(), r.theText);
      // revise the choice of statements available
      setStatements(r.nextChoice);
    }
    else
    {
      conversation.addStatement(person.getName(), "...<click>... can't establish a connection.");
      setStatements(5);
    }
     // update the view of the conversation
    speechList.setListData(conversation);
  }

  public void response(int idx)
  {
    // Respond to the current statement
    // get info on the statement
    MarsMyStatement s = new MarsMyStatement( ((MarsMyStatement) myStatements.elementAt(idx)));
    // Now update the person's mood
    if (person.personality == "D")
    {
      person.mood = person.mood + s.moodImpactD;
    }
    if (person.personality == "I")
    {
      person.mood = person.mood + s.moodImpactI;
    }
    if (person.personality == "C")
    {
      person.mood = person.mood + s.moodImpactC;
    }
    if (person.personality == "S")
    {
      person.mood = person.mood + s.moodImpactS;
    }
    // Update the person's record
    if(theFrame.mars.People.elementAt(personId) != null)
    {
      ((MarsPerson) theFrame.mars.People.elementAt(personId)).mood = person.mood;
    }
    else
    {
      //conversation.addStatement(person.getName(), "...<click>... system error... lost contact.");
      speak(personId, "...<click>... system error... lost contact.");
      setStatements(5);
    }
    // Now find the best response
    MarsResponse r = theFrame.mars.Responses.selectResponse(s.response, personId);
    if(r != null)
    {
      // update the conversation
      //conversation.addStatement(person.getName(), r.theText);
      speak(personId, r.theText);
      // revise the choice of statements available
      setStatements(r.nextChoice);
    }
    else
    {
      //conversation.addStatement(person.getName(), "...<click>... system error... unable to respond.");
      speak(personId,"...<click>... system error... unable to respond.");
      setStatements(5);
    }
     // update the view of the conversation
    speechList.setListData(conversation);
  }
/*  public void paint(Graphics g)
  {
    paintChildren(g);
  }
*/
  public void userChoice(int index)
  {
    // make note of what the user has selected
    switch(agreedAction)
    {
      case 0:
        // do nothing
        break;
      case 1:
        // Find out what activity to start
        switch (agreedActivity)
        {
          case -1: // The default value - this is if the user has selected an activity type
            // Find out what type of activity
            agreedActivity = index + 1;
            break;
          case 1: // construction
            // Find out what to construct
            agreedActivitySpecial = this.myStatements.getMyStatement(index).getSpecial();
            // This will need to be updated...
          case 2: // research
            // find out what to research
            agreedActivitySpecial = this.myStatements.getMyStatement(index).getSpecial();
            // This will need to be updated...
        }
        break;
      case 2:
        break;
      case 3:
        break;
    }
  }
  
  public void speak(int speaker, String statement)
  {
    String speakersName = ((MarsPerson) theFrame.mars.People.elementAt(speaker)).getName();
    // add the statement to the record of the conversation
    conversation.addStatement(speakersName, statement);
    lastSpeaker = speaker;
    theFrame.mars.logEvent("Conversation: " + speakersName + " said '" + statement + "'");
  
    // highlight the speakers' face
    int i = 0;
    for (i=0; i<listOfFaces.size(); i++)
    {
      ((MarsPersonFacePanel) listOfFaces.elementAt(i)).setActive(false);
    }
    for (i=0; i<listOfFaces.size(); i++)
    {
      if ( ((MarsPersonFacePanel) listOfFaces.elementAt(i)).getPersonId() == speaker)
      {
        ((MarsPersonFacePanel) listOfFaces.elementAt(i)).setActive(true);
      }
    }
    speechList.setListData(conversation);
  }
  
  public void updateConversation()
  {
    // Do nothing
  }
  
  public void saySomething(int speaker)
  {
    // say nothing...
  }
}
