// ============================================================================
// File:               $File$
//
// Project:            
//
// Purpose:            
//
// Author:             Rammi
//
// Copyright Notice:   (c) 2008  Rammi (rammi@caff.de)
//
// Latest change:      $Date$
//
// History:	       $Log$
//=============================================================================
package de.caff.asteroid.analysis.statistics;

import de.caff.i18n.I18n;
import de.caff.asteroid.Property;
import de.caff.asteroid.analysis.DumpFile;
import de.caff.gimmicks.swing.ResourcedAction;

import javax.swing.*;
import java.util.Collection;
import java.awt.event.ActionEvent;

/**
 *  Basic implementation of dump file statistics.
 */
public abstract class AbstractBasicDumpFileStatistics
        implements DumpFileStatistics
{
  static {
    I18n.addAppResourceBase("de.caff.asteroid.analysis.statistics.resources.AbstractBasicDumpFileStatistics");
  }
  private static class ShowStatisticsAction
          extends AbstractAction
  {
    private DumpFile dumpFile;
    private DumpFileStatistics statistics;

    /**
     * Create a resourced action with the default locale.
     *
     * @param dumpFile   dump file to analyse
     * @param statistics statistics to show
     */
    ShowStatisticsAction(DumpFile dumpFile, DumpFileStatistics statistics)
    {
      super(statistics.getTitle());
      this.dumpFile = dumpFile;
      this.statistics = statistics;
    }

    /**
     * Invoked when an action occurs.
     */
    public void actionPerformed(ActionEvent e)
    {
      statistics.analyse(dumpFile.getInfos());
      StatisticsDialog dialog = new StatisticsDialog(statistics);
      dialog.setVisible(true);
    }

    @Override
    protected Object clone() throws CloneNotSupportedException
    {
      return super.clone();
    }
  }
  protected static final String TAG_HTML              = "html";
  protected static final String TAG_HEAD              = "head";
  protected static final String TAG_TITLE             = "title";
  protected static final String TAG_BODY              = "body";
  protected static final String TAG_HEADER_MAIN       = "h1";
  protected static final String TAG_HEADER_SECTION    = "h2";
  protected static final String TAG_HEADER_SUBSECTION = "h3";
  protected static final String TAG_TABLE             = "table";
  protected static final String TAG_TABLE_ROW         = "tr";
  protected static final String TAG_TABLE_HEAD        = "th";
  protected static final String TAG_TABLE_CELL        = "td";
  protected static final String TAG_STYLE             = "style";
  protected static final String VAL_ALIGN_LEFT        = "text-align:left;";
  protected static final String VAL_ALIGN_RIGHT       = "text-align:right";

  /**
   *  Escape characters which have a special meaning in HTML.
   *  @param str string which may contain special characters
   *  @return string with HTML escapes
   */
  protected static String escapeHtml(String str)
  {
    StringBuilder b = new StringBuilder();
    for (char ch: str.toCharArray()) {
      switch (ch) {
      case '&':
        b.append("&amp;");
        break;
      case '<':
        b.append("&lt;");
        break;
      case '>':
        b.append("&gt;");
        break;
      case '"':
        b.append("&quot;");
        break;
      default:
        b.append(ch);
      }
    }
    return b.toString();
  }

  protected static String attr(String name, Object value)
  {
    return String.format("%s=\"%s\"", name, escapeHtml(value.toString()));
  }

  protected static void appendOpenTag(StringBuilder b, String tag, String ... attrs)
  {
    b.append('<').append(tag);
    for (String att: attrs) {
      b.append(' ').append(att);
    }
    b.append('>');
  }

  protected static void appendCloseTag(StringBuilder b, String tag)
  {
    b.append("</").append(tag).append('>');
  }

  protected static void appendStandaloneTag(StringBuilder b, String tag, String ... attrs)
  {
    b.append('<').append(tag);
    for (String att: attrs) {
      b.append(' ').append(att);
    }
    b.append("/>");
  }

  protected static void appendTaggedText(StringBuilder b, String text, String tag, String ... attrs)
  {
    appendOpenTag(b, tag, attrs);
    appendText(b, text);
    appendCloseTag(b, tag);
  }

  protected static void appendText(StringBuilder b, String text)
  {
    b.append(escapeHtml(text));
  }

  protected void appendContentTable(StringBuilder b, Collection<Property> properties)
  {
    appendOpenTag(b, TAG_TABLE, attr("border", 1));
    {
      appendOpenTag(b, TAG_TABLE_ROW);
      appendTaggedText(b, I18n.getString("abdfsRowHeadName"), TAG_TABLE_HEAD);
      appendTaggedText(b, I18n.getString("abdfsRowHeadValue"), TAG_TABLE_HEAD);
      appendCloseTag(b, TAG_TABLE_ROW);
    }
    for (Property property: properties) {
      appendOpenTag(b, TAG_TABLE_ROW);
      appendTaggedText(b, property.getName(), TAG_TABLE_CELL, attr(TAG_STYLE, getLeftColumnAlign()));
      appendTaggedText(b, property.getValueString(), TAG_TABLE_CELL, attr(TAG_STYLE, getRightColumnAlign()));
      appendCloseTag(b, TAG_TABLE_ROW);
    }
    appendCloseTag(b, TAG_TABLE);
  }

  /**
   * Append the summary report of this statistics to the document.
   *
   * @param html HTML document to which the report is added
   */
  public void appendToHtml(StringBuilder html)
  {
    appendTaggedText(html, getTitle(), TAG_HEADER_SECTION);
    appendContentTable(html, getProperties());
  }

  /**
   * Return a complete html document containing a summary report for the data from the lastest analysis.
   *
   * @return summary report in HTML format
   */
  public String getHtmlReport()
  {
    StringBuilder b = new StringBuilder();
    appendOpenTag(b, TAG_HTML);
    appendOpenTag(b, TAG_HEAD);
    appendTaggedText(b, getTitle(), TAG_TITLE);
    appendCloseTag(b, TAG_HEAD);
    appendOpenTag(b, TAG_BODY);
    appendHtmlBody(b);
    appendCloseTag(b, TAG_BODY);
    appendCloseTag(b, TAG_HTML);
    return b.toString();
  }

  /**
   *  Append the inner part of the HTML body.
   *  @param b string builder to append
   */
  protected void appendHtmlBody(StringBuilder b)
  {
    appendTaggedText(b, getTitle(), TAG_HEADER_MAIN);
    appendContentTable(b, getProperties());
  }

  protected String getLeftColumnAlign()
  {
    return VAL_ALIGN_LEFT;
  }

  protected String getRightColumnAlign()
  {
    return VAL_ALIGN_RIGHT;
  }

  /**
   *  Get a popup menu with actions for showing various statitics.
   *  @param dumpFile dump file to analyse
   *  @return popup menu
   */
  public static JPopupMenu getStatisticsMenu(DumpFile dumpFile)
  {
    JPopupMenu popup = new JPopupMenu("menuTitleStatistics");
    popup.add(new ShowStatisticsAction(dumpFile, new KeyStatistics()));
    popup.add(new ShowStatisticsAction(dumpFile, new BulletStatistics()));
    popup.add(new ShowStatisticsAction(dumpFile, new AnswerTimesStatistics()));
    return popup;
  }

  protected static String percentify(double part, double total)
  {
    return total == 0  ?
            "???"  :
            String.format("%3.2f%%", 100*part/total);
  }
}
