/*
 * File    : SessionReg.java
 * Created : 29-jan-2002 11:06
 * By      : fbusquets
 *
 * JClic - Authoring and playing system for educational activities
 *
 * Copyright (C) 2000 - 2018 Francesc Busquets & Departament
 * d'Educacio de la Generalitat de Catalunya
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details (see the LICENSE file).
 */

package edu.xtec.jclic.report;

import edu.xtec.jclic.Activity;
import edu.xtec.jclic.bags.ActivitySequenceElement;
import edu.xtec.jclic.project.JClicProject;
import edu.xtec.util.Html;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @author Francesc Busquets (fbusquets@xtec.cat)
 * @version 1.0
 */
public class SessionReg implements java.io.Serializable {

  List<SequenceReg> sequences;
  SequenceReg currentSequence = null;
  public java.util.Date started;
  protected long timeMillis;
  String projectName;
  protected transient Info info;
  String code;

  /** Creates new SessionReg */
  public SessionReg(JClicProject jcp) {
    this(jcp.getName(), jcp.code);
  }

  public SessionReg(String projectName, String code) {
    sequences = new CopyOnWriteArrayList<SequenceReg>();
    currentSequence = null;
    started = new java.util.Date();
    timeMillis = System.currentTimeMillis();
    this.projectName = projectName;
    this.code = code;
    info = new Info();
  }

  public String toHtmlString(edu.xtec.util.Messages msg, boolean recalcInfo, boolean writeProjectName) {
    String prefix = "report_";
    Html html = new Html(3000);
    if (recalcInfo)
      info.recalc();

    if (info.numSequences > 0) {
      if (writeProjectName) {
        html.append("<TR STYLE=\"").append(msg.get("about_window_html_style_table_header2")).append("\">");
        html.append("<TD COLSPAN=\"6\">");
        html.bold(msg.get(prefix + "project") + Html.NBSP + projectName);
        html.td(false).tr(false);
      }
      html.append("<TR STYLE=\"").append(msg.get("about_window_html_style_table_header")).append("\">");
      html.td(msg.get(prefix + "lb_sequence"), Html.CENTER, true, null);
      html.td(msg.get(prefix + "lb_activity"), Html.CENTER, true, null);
      html.td(msg.get(prefix + "lb_solved"), Html.CENTER, true, null);
      html.td(msg.get(prefix + "lb_actions"), Html.CENTER, true, null);
      html.td(msg.get(prefix + "lb_score"), Html.CENTER, true, null);
      html.td(msg.get(prefix + "lb_time"), Html.CENTER, true, null);
      html.tr(false);
      Iterator<SequenceReg> it = sequences.iterator();
      while (it.hasNext())
        html.append(it.next().toHtmlString(msg));

      html.append("<TR STYLE=\"").append(msg.get("about_window_html_style_table_totals")).append("\">");
      html.td(msg.get(prefix + "lb_totals"), Html.LEFT, true, null);
      html.td(msg.getNumber(info.nActivities), Html.RIGHT, true, null);
      html.td(msg.getNumber(info.nActSolved) + " (" + msg.getPercent(info.percentSolved) + ")", Html.RIGHT, true, null);
      html.td(msg.getNumber(info.nActions), Html.RIGHT, true, null);
      html.td(msg.getPercent(info.tScore), Html.RIGHT, true, null);
      html.td(msg.getHmsTime(info.tTime), Html.RIGHT, true, null);
      html.tr(false);
    }

    return html.toString();
  }

  public Info getInfo(boolean recalc) {
    if (recalc)
      info.recalc();
    return info;
  }

  public class Info {
    public int numSequences, nActivities, nActSolved, nActScore, percentSolved, nActions;
    public long tScore, tTime;

    protected Info() {
      clear();
    }

    protected void clear() {
      numSequences = nActivities = nActSolved = nActScore = percentSolved = nActions = 0;
      tScore = tTime = 0L;
    }

    public void recalc() {
      clear();
      Iterator<SequenceReg> it = sequences.iterator();
      while (it.hasNext()) {
        SequenceReg.Info sri = it.next().getInfo(true);
        if (sri.nActivities > 0) {
          numSequences++;
          if (sri.nActClosed > 0) {
            nActivities += sri.nActClosed;
            nActions += sri.nActions;
            if (sri.nActScore > 0) {
              nActScore += sri.nActScore;
              tScore += (sri.tScore * sri.nActScore);
            }
            tTime += sri.tTime;
            nActSolved += sri.nActSolved;
          }
        }
      }
      if (nActScore > 0)
        tScore /= nActScore;
      if (nActivities > 0)
        percentSolved = (nActSolved * 100) / nActivities;
    }
  }

  @Override
  protected void finalize() throws Throwable {
    end();
    super.finalize();
  }

  public void end() {
    endSequence();
  }

  public void endSequence() {
    if (currentSequence != null && currentSequence.totalTime == 0)
      currentSequence.endSequence();
    currentSequence = null;
  }

  public void newSequence(ActivitySequenceElement ase) {
    endSequence();
    currentSequence = new SequenceReg(ase);
    sequences.add(currentSequence);
  }

  public void newActivity(Activity act) {
    if (currentSequence != null)
      currentSequence.newActivity(act);
  }

  public void endActivity(int score, int numActions, boolean solved) {
    if (currentSequence != null)
      currentSequence.endActivity(score, numActions, solved);
  }

  public void newAction(String type, String source, String dest, boolean ok) {
    if (currentSequence != null)
      currentSequence.newAction(type, source, dest, ok);
  }

  public String getCurrentSequenceTag() {
    if (currentSequence == null)
      return null;
    return currentSequence.name;
  }

  public SequenceReg.Info getCurrentSequenceInfo() {
    return currentSequence == null ? null : currentSequence.getInfo(true);
  }
}
