package com.Series40Book.midp.model.questions;

import javax.microedition.io.*;
import java.io.*;
import java.util.*;

import com.Series40Book.midp.controller.*;
import com.Series40Book.midp.model.*;

/**
 * Navigate among downloaded questions. It is a singleton
 * abstract class: the application needs to use a subclass
 * that defines the actual questions mechanism.
 *
 */
public abstract class QuestionsNavigator {


  // The current RecordId in the questionStore
  protected int currentId;
  protected TriviaQuestion currentQuestion;
  protected Hashtable answers;

  protected static String url;
  public long time;

  // Numbers of correct/wrong answers
  public int correctNum;
  public int wrongNum;
  public int totalNum;

  public static int CORRECT_ANSWER = 1;
  public static int WRONG_ANSWER = 2;
  public static int NA_ANSWER = 3;

  private static QuestionsNavigator qn = null;

  public static void setUrl (String u) throws Exception {
    url = u;
  }

  // We could choose different implementation classes
  // in this method
  public static QuestionsNavigator getInstance () throws Exception {
    if (url == null || "".equals(url)) {
      throw new Exception ("Please set the URL first");
    }
    if (qn == null) {
      //#if LargeRMS
      {
        qn = new QuestionsNavigatorRMS ();
      }
      //#else
      {
        qn = new QuestionsNavigatorRAM ();
      }
      //#endif
    }
    return qn;
  }

  public abstract void initSession () throws Exception;

  // Reset the answers
  public void resetSession () {
    answers = new Hashtable ();
    correctNum = 0;
    wrongNum = 0;
    currentId = 0;
  }

  // Return the question text of the current question
  public String getQuestion () {
    String result;
    try {
      result = currentQuestion.question;
    } catch (Exception e) {
      result = "";
    }
    return result;
  }

  // Stores the answer for the current question
  public int storeAnswer (int ans) {
    answers.put(currentQuestion.questionId,
                new Integer(ans));
    // prepare the return code
    int status = NA_ANSWER;
    if (currentQuestion.sendAnswer) {
      if (currentQuestion.answerId == ans) {
        status = CORRECT_ANSWER;
        correctNum++;
      } else {
        status = WRONG_ANSWER;
        wrongNum++;
      }
    }
    return status;
  }

  // Return the current set of choices
  public String [] getChoices () {
    return currentQuestion.choices;
  }

  // Return the current answerHint
  public String getAnswerHint () {
    return currentQuestion.answerHint;
  }

  // Return the PNG image array for the current question
  public byte [] getImage () {
    return currentQuestion.image;
  }

  // Return the MIDI array for the current question
  public byte [] getSound () {
    return currentQuestion.sound;
  }

  public abstract void download (String category,
                WorkerRunnable gauge) throws Exception;

  // Move to the next question.
  // return true if there is more question
  public abstract boolean next ();


  // If all the questions have pre-downloaded answers,
  // skip the network operation.
  public boolean isReady () {
    try {
      time = TheTimer.report() / 1000;
      return (wrongNum + correctNum == totalNum);
    } catch (Exception e) {
      e.printStackTrace ();
      return false;
    }
  }

  // If any question in the set does not have a pre-downloaded
  // answer, ask the server to calculate the scores.
  public void submit (WorkerRunnable worker)
                             throws Exception {

    HttpConnection conn = null;
    DataInputStream hdin = null;
    DataOutputStream hdout = null;

    try {
      conn = (HttpConnection) Connector.open( url );
      conn.setRequestMethod(HttpConnection.POST);
      hdout = conn.openDataOutputStream();
      hdout.writeInt(OpCodes.SUBMIT); // Submit opcode

      int numAnswers = answers.size ();
      hdout.writeInt(numAnswers);

      Enumeration enu = answers.keys ();
      int i = 0;
      while (enu.hasMoreElements()) {
        i++;
        worker.updateWaitStatus ("Sending item " + i);
        String questionId = (String) enu.nextElement();
        hdout.writeUTF(questionId);
        hdout.writeInt(((Integer)
            answers.get(questionId)).intValue());
      }
      hdout.flush();

      hdin = conn.openDataInputStream();
      correctNum = hdin.readInt();
      wrongNum = hdin.readInt();

    } catch (Exception e) {
      e.printStackTrace();
      throw new Exception ("Submit failed");
    } finally {
      try {
        if (conn != null) conn.close();
        if (hdout != null) hdout.close();
        if (hdin != null) hdin.close();
      } catch (Exception e) {}
    }
  }

}
