package uk.co.patrickhaston.mars;

/**
 * the class defining each person in the game
 */
public class MarsPerson extends MarsLocatedObject 
{
  /**
   * the id of the settlement that this person is based at
   */
  private int settlement;

  /**
   * an array of integers showing which activities
   * this person is working on each day of the week
   * 0 (Monday) through to 6 (Sunday)
   */
  private int[] activity; // 0= Monday - 6 = Sunday

  public int role;
  public int resourcesOwned;
  public int currentStep;
  
  /**
   * a letter indicating this person's personality style
   * D - Dominant (typical commander)
   * I - inspirational (typical entertainer)
   * S - submissive (typical worker)
   * C - cautious (typical scientist)
   */
  public String personality; 

  public int mood;
  public static int DELIGHTED = 1;
  public static int HAPPY = 2;
  public static int CONTENT = 3;
  public static int OK = 4;
  public static int ANNOYED = 5;
  public static int ANGRY = 6;
  public static int FURIOUS = 7;
  
  private int faceId;
  private int nameId;

  public MarsPerson(int id)
  {
    super(id);
    settlement = 0;
    activity = new int[7];
    for (int i=0; i<7; i++)
    {
      activity[i] = 0;
    }
    role = 0;
    resourcesOwned = 0;
    currentStep = 0;
    personality = "";
    mood = 0;
    faceId = 0;
    nameId = 0;
  }

  public MarsPerson(MarsPerson p)
  {
    super((MarsLocatedObject) p);
    if (p == null)
    {
      settlement = 0;
      activity = new int[7];
      for (int i=0; i<7; i++)
      {
        activity[i] = 0;
      }
      role = 0;
      resourcesOwned = 0;
      currentStep = 0;
      personality = "";
      mood = 0;
      faceId = 0;
      nameId = 0;
    }
    else
    {
      settlement = p.settlement;
      activity = new int[7];
      for (int i=0; i<7; i++)
      {
        activity[i] = p.activity[i];
      }
      role = p.role;
      resourcesOwned = p.resourcesOwned;
      currentStep = p.currentStep;
      personality = p.personality;
      mood = p.mood;
      faceId = p.faceId;
      nameId = p.nameId;
    }
  }
  
  public MarsPerson(String line)
  {
    super(line);
    
    settlement = readInteger(line, 3);
    activity = new int[7];
    for (int i=0; i<7; i++)
    {
      activity[i] = readInteger(line, 4+i);
    }
    role = readInteger(line, 11);
    resourcesOwned = readInteger(line, 12);
    currentStep = readInteger(line, 13);
    personality = readString(line, 14);
    mood = readInteger(line, 15);
    faceId = readInteger(line, 16);
    nameId = readInteger(line, 17);
  }

  public String toString()
  {
    String s = super.toString();
    
    s = s + new Integer(settlement).toString() + ", Activities (";
    for (int i=0; i<7; i++)
    {
      s = s +  //new Integer(i).toString() + ","
        new Integer(activity[i]).toString() + ",";
    }
    s = s + ") " + getRoleName(role) + ",";
    s = s + new Integer(resourcesOwned).toString() + ",";
    s = s + new Integer(currentStep).toString() + ",";
    s = s + " personality " + personality;
    s = s + " mood: " + getMoodName();
    s = s + " faceId " + faceId;
    s = s + " nameId " + nameId;

    return s;
  }

  public String toFile()
  {
    String s = super.toString();
    
    s = s + new Integer(settlement).toString() + ",";
    for (int i=0; i<7; i++)
    {
      s = s + new Integer(activity[i]).toString() + ",";
    }
    s = s + new Integer(role).toString() + ",";
    s = s + new Integer(resourcesOwned).toString() + ",";
    s = s + new Integer(currentStep).toString() + ",";
    s = s + personality + ",";
    s = s + new Integer(mood).toString() + ",";
    s = s + faceId + "," + nameId + ",";

    return s;
  }

  public void subtractResource(MarsModel model, MarsResource r)
  {
    ((MarsResource) model.gameResources.elementAt(resourcesOwned)).subtractResource(r);
  }

  public void addResource(MarsModel model, MarsResource r)
  {
    ((MarsResource) model.gameResources.elementAt(resourcesOwned)).addResource(r);
  }
  
  public int getStoredResources()
  {
    return resourcesOwned;
  }
  
  public void update(MarsModel model, int personId)
  {
    // update this person
    // if they aren't doing anything, then they need to choose an activity
    // first, what day is today?
    int day = 0;
    switch (model.gameDate.get(model.gameDate.DAY_OF_WEEK))
    {
      case /*model.gameDate.MONDAY*/ 0: day = 0; break;
      case /*model.gameDate.TUESDAY*/ 1: day = 1; break;
      case /*model.gameDate.WEDNESDAY*/ 2: day = 2; break;
      case /*model.gameDate.THURSDAY*/ 3: day = 3; break;
      case /*model.gameDate.FRIDAY*/ 4: day = 4; break;
      case /*model.gameDate.SATURDAY*/ 5: day = 5; break;
      case /*model.gameDate.SUNDAY*/ 6: day = 6; break;
    }
    if (activity[day] == 0)
    {
      // choose an activity for themselves
      chooseNewActivity(day, personId, model);
    }
    else
    {
      if( model.Activities.getStatus(activity[day]) == MarsActivity.COMPLETE)
      {
        chooseNewActivity(day, personId, model);
      }
    }
  }
  
  public void chooseNewActivity(int day, int personId, MarsModel model)
  {
    if( model.logEnabled ) model.logEvent("Choosing new activity for " + this.getName());
    // first thought is to do the same as another day...
    int act = getExistingActivity(day, model);
    if ( act > 0 )
    {
      activity[day] = act;
      if( model.logEnabled ) model.logEvent(this.getName() + 
        " has chosen the same activity as yesterday (id=" + act + ").");
    }
    
    // what about helping someone else out?
    act = getFriendActivity(model);
    if ( act > 0 )
    {
      activity[day] = act;
      if( model.logEnabled ) 
        model.logEvent(this.getName() + 
          " is going to help someone else with their activity (id=" + act + ").");
    }
    
    // need to choose a new activity
    MarsGoal g = new MarsGoal(model.Goals.nextStep(role, currentStep));
    // move their goals forward to the next step
    currentStep++;
    try
    {
      activity[day] = model.Activities.startNewActivity(g.activity, g.special, personId, settlement);

      if( model.logEnabled )
        model.logEvent("New activity chosen = " + ((MarsActivity) model.Activities.elementAt(activity[day])).getDescription() );

      model.messageFrom("Starting " + ((MarsActivity) model.Activities.elementAt(activity[day])).getDescription(), personId);
    }
    catch (Exception e)
    {
      System.out.println("Error in MarsPerson.chooseNewActivity() for person " + 
        personId + " on day " + day + " : " + e.getMessage());
    }
  }
  
  public int getExistingActivity(int day, MarsModel model)
  {
    // check the activities being done by this person on the rest of the week
    for (int d=1; d<7; d++)
    {
      int otherDay = day - d;
      if ( otherDay < 0 ) otherDay = otherDay + 7;
      if ( activity[otherDay] > 0)
      {
        if( model.Activities.getStatus(activity[otherDay]) == MarsActivity.IN_PROGRESS)
        {
          return activity[otherDay];
        }
      }
    }
    return 0;
  }
  
  public int getFriendActivity(MarsModel model)
  {
    // get a list of the activities
    int actCount = model.Activities.count();
    if( actCount == 0 ) return 0;
    
    int[] actScore = new int[actCount];
    int[] actId = new int[actCount];
    int a = 0;
    
    actId[ 0 ] = model.Activities.getFirstId();
    while( actId[ a ] > 0 ) 
    {
      if( model.Activities.getStatus( actId[ a ] ) == MarsActivity.IN_PROGRESS ) return actId[ a ];
      
      model.Activities.getNextId( actId[ a ] );
    }
    return 0;
  }
  
  public void activityStopped(int activityId)
  {
    for (int i=0; i<7; i++)
    {
      if (activity[i] == activityId) activity[i] = 0;
    }
  }
  
  public int getMood()
  {
    if (mood > 75) return 1; // delighted
    if (mood > 50) return 2; // Happy
    if (mood > 20) return 3; // Content
    if (mood > -20) return 4; // Ok
    if (mood > -50) return 5; // Annoyed
    if (mood > -75) return 6; // Angry
    return 7; // Furious
  }
  
  public String getMoodName()
  {
    switch(getMood())
    {
      case 1: return "Delighted";
      case 2: return "Happy";
      case 3: return "Content";
      case 4: return "Ok";
      case 5: return "Annoyed";
      case 6: return "Angry";
      case 7: return "Furious";
    }
    return "No mood";
  }
  
  public int getFaceId()
  {
    return faceId;
  }
  
  public int getNameId()
  {
    return nameId;
  }

  public void setSettlement(int settlement)
  {
    this.settlement = settlement;
  }

  public int getSettlement()
  {
    return settlement;
  }
  
  public int getActivity(int day)
  {
    return activity[day];
  }
  
  public void setActivity(int day, int id)
  {
    activity[day] = id;
  }
}

