// ============================================================================
// File:               $File$
//
// Project:            
//
// Purpose:            
//
// Author:             Rammi
//
// Copyright Notice:   (c) 2008  Rammi (rammi@caff.de)
//                     This code is in the public domain.
//                     Use at own risk.
//                     No guarantees given.
//
// Latest change:      $Date$
//
// History:	       $Log$
//=============================================================================
package de.caff.asteroid.analysis;

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

/**
 *  Basic class for timelines.
 */
public abstract class AbstractBasicTimeLine
        extends JComponent
{
  /** Top and bottom border (contains marker triangles). */
  protected static final int MARKER_BORDER_Y = 8;
  /** Left and right border. */
  protected static final int MARKER_BORDER_X = MARKER_BORDER_Y /2 + 2;
  /** Background color. */
  protected static final Color BACKGROUND_COLOR = Color.white;
  /** Color for frames in game, w/o ship. */
  protected static final Color NO_SHIP_COLOR = Color.blue;
  /** Color for frames in game, w/o ship. */
  protected static final Color WITH_SHIP_COLOR = new Color(0x40, 0x40, 0xFF);
  /** Color for frames between games. */
  protected static final Color BETWEEN_GAMES_COLOR = Color.orange;
  /** Color for frames after dump end (only when reading dump). */
  protected static final Color AFTER_DUMP_END_COLOR = Color.gray;

  /**
   *  Map an index to a screen position.
   *  @param index index
   *  @return associated screen x on this component
   */
  protected int indexToScreen(int index)
  {
    return isValid() ? (int)(index * getScale() + MARKER_BORDER_X) : -1;
  }

  /**
   *  Get the color for a mark.
   *  @param mark mark
   *  @return associated color
   */
  private static final Color getColor(DumpFile.Mark mark)
  {
    switch (mark.getMarkType()) {
    case SHIP_APPEARS:
      return WITH_SHIP_COLOR;
    case SHIP_VANISHES:
    case GAME_START:
      return NO_SHIP_COLOR;
    case GAME_END:
      return BETWEEN_GAMES_COLOR;
    case DUMP_END:
      return AFTER_DUMP_END_COLOR;
    }
    return null;
  }

  /**
   *  Paints the component.
   *  @param g the <code>Graphics</code> object to protect
   *  @see #paint
   *  @see javax.swing.plaf.ComponentUI
   */
  @Override
  protected void paintComponent(Graphics g)
  {
    g.setColor(BACKGROUND_COLOR);
    g.fillRect(0, 0, getWidth(), getHeight());


    if (getFrameCount() == 0) {
      return;
    }

    DumpFile.Mark prevMark = null;
    for (DumpFile.Mark mark: getMarks()) {
      if (prevMark != null) {
        int left = indexToScreen(prevMark.getFrameIndex());
        int right = indexToScreen(mark.getFrameIndex());
        g.setColor(getColor(prevMark));
        g.fillRect(left, MARKER_BORDER_Y, right - left, getHeight() - 2* MARKER_BORDER_Y);
      }
      prevMark = mark;
    }
    if (prevMark != null) {
      int left = indexToScreen(prevMark.getFrameIndex());
      int right = indexToScreen(getFrameCount());
      g.setColor(getColor(prevMark));
      g.fillRect(left, MARKER_BORDER_Y, right - left, getHeight() - 2* MARKER_BORDER_Y);
    }
  }

  /**
   *  Get the marks to display.
   *  @return marks
   */
  protected abstract Collection<DumpFile.Mark> getMarks();

  /**
   * Get the number of frames to display.
   * @return frame count
   */
  public abstract int getFrameCount();

  /**
   *  Get the scaling between screen and indices.
   *  @return screen/index
   */
  protected double getScale()
  {
    int size = getFrameCount();
    return size > 0 ? (getWidth() - 2* MARKER_BORDER_X)/(double)size : -1;
  }
}
