// ============================================================================
// 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;

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.util.Collection;

/**
 *  Explosion in the game.
 *
 *  Please note that this currently only exists to display something.
 *
 *  This class is part of a solution for a
 *  <a href="http://www.heise.de/ct/creativ/08/02/details/">competition by the German computer magazine c't</a>
 */
public class Explosion
        extends GameObject
{
  /** Color used for explosions. */
  private static final Color EXPLOSION_COLOR = new Color(0x80, 0x80, 0x80);
  /** Glyph for XXL explosion. */
  public static final Glyph XXL_GLYPH = // 0x880
          new Glyph(new byte[] {16, 0, 0, 16, 0, 7, 32, 16, 0, 32, 16, 7, 16, 32, 0, 16, 32, 7, -8, 24, 0, -8, 24, 7, -24, 32, 0, -24, 32, 7, -24, 16, 0, -24, 16, 7, -32, -8, 0, -32, -8, 7, -24, -32, 0, -24, -32, 7, 8, -24, 0, 8, -24, 7, 32, -32, 0, 32, -32, 7});
  /** Glyph for XL explosion. */
  public static final Glyph XL_GLYPH =  // 0x896
          new Glyph(new byte[] {14, 0, 0, 14, 0, 7, 28, 14, 0, 28, 14, 7, 14, 28, 0, 14, 28, 7, -7, 21, 0, -7, 21, 7, -21, 28, 0, -21, 28, 7, -21, 14, 0, -21, 14, 7, -28, -7, 0, -28, -7, 7, -21, -28, 0, -21, -28, 7, 7, -21, 0, 7, -21, 7, 28, -28, 0, 28, -28, 7});
  /** Glyph for L explosion. */
  public static final Glyph L_GLYPH =   // 0x8B5
          new Glyph(new byte[] {12, 0, 0, 12, 0, 7, 24, 12, 0, 24, 12, 7, 12, 24, 0, 12, 24, 7, -6, 18, 0, -6, 18, 7, -18, 24, 0, -18, 24, 7, -18, 12, 0, -18, 12, 7, -24, -6, 0, -24, -6, 7, -18, -24, 0, -18, -24, 7, 6, -18, 0, 6, -18, 7, 24, -24, 0, 24, -24, 7});
  /** Glyph for S explosion. */
  public static final Glyph S_GLYPH =   // 0x8D0
          new Glyph(new byte[] {10, 0, 0, 10, 0, 7, 20, 10, 0, 20, 10, 7, 10, 20, 0, 10, 20, 7, -5, 15, 0, -5, 15, 7, -15, 20, 0, -15, 20, 7, -15, 10, 0, -15, 10, 7, -20, -5, 0, -20, -5, 7, -15, -20, 0, -15, -20, 7, 5, -15, 0, 5, -15, 7, 20, -20, 0, 20, -20, 7});

  /** The different explosion types. */
  public static enum Type {
    XXL(XXL_GLYPH),
    XL(XL_GLYPH),
    L(L_GLYPH),
    S(S_GLYPH);


    private final Shape shape;
    Type(Glyph glyph)
    {
      shape = glyph.getPath();
    }

    public Shape getShape()
    {
      return shape;
    }
  }
  /** Type of explosion. */
  private Type type;
  /** Scale of explosion (inverse). */
  private int scale;

  /**
   *  Constructor.
   *  @param x   center x
   *  @param y   center y
   *  @param scale  scale from MAME
   *  @param type   type of explosion
   */
  public Explosion(int x, int y, int scale, Type type)
  {
    super(x, y);
    this.type = type;
    switch (scale) {
    case 0:
      this.scale = 1;
      break;

    case 15:
      this.scale = 2;
      break;

    case 14:
      this.scale = 4;
      break;

    case 13:
      this.scale = 8;
      break;

    case 12:
      this.scale = 16;
      break;

    case 11:
      this.scale = 32;
      break;

    default:
      System.out.println("Unexpected explosion scaling: "+scale);
      this.scale = 1;
    }
  }

  /**
   *  Get the type.
   *  @return type
   */
  public Type getType()
  {
    return type;
  }

  /**
   * Get the size of the object.
   * <p/>
   * The size returned by this method is half the length of a square which contains the object,
   * so the object's bounding box is between (x - size, y - size) and (x + size, y + size).
   *
   * @return object size
   */
  public int getSize()
  {
    return type.getShape().getBounds().width/(2*scale);
  }

  /**
   * Returns a string representation of the object.
   *
   * @return a string representation of the object.
   */
  @Override
  public String toString()
  {
    return String.format("Explosion(%s)@(%d,%d)*%d", type, getX(), getY(), getSize());
  }

  /**
   * Draw the object.
   *
   * @param g graphics context
   */
  public void draw(Graphics2D g)
  {
    Graphics2D g2 = (Graphics2D)g.create(); // copy to change stroke
    g2.setColor(EXPLOSION_COLOR);
    //g2.setStroke(new BasicStroke(type.size/8/scale));
    g2.draw(getExplosionShape());
  }

  /**
   *  Get the shape of this explosion.
   *  @return explosion shape
   */
  public Shape getExplosionShape()
  {
    AffineTransform trafo = new AffineTransform(1.0/scale, 0, 0, 1.0/scale, x, y);
    return trafo.createTransformedShape(type.getShape());
  }

  /**
   * Get the properties of this object.
   *
   * @return collection of properties
   */
  @Override
  public Collection<Property> getProperties()
  {
    Collection<Property> props = super.getProperties();
    props.add(new Property<Type>("Explosion Type", getType()));
    props.add(new Property<Integer>("Scale", scale));
    return props;
  }

  /**
   * Get the bounding box of this rectangle.
   *
   * @return the bounding box
   */
  public Rectangle getBounds()
  {
    return getExplosionShape().getBounds();
  }

  /**
   * Get the type of game object.
   *
   * @return game object type
   */
  public String getObjectType()
  {
    return "Explosion";
  }

  /**
   * Access method for visitor pattern.
   *
   * @param visitor visitor
   */
  public void visitedBy(GameObjectVisitor visitor)
  {
    visitor.handle(this);
  }
}