/*  Copyright (C) 2003-2011 Raik Nagel
    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.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

package net.sf.jabref.about ;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageProducer;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Enumeration;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.UIManager;
import javax.swing.border.BevelBorder;

import net.sf.jabref.GUIGlobals;
import net.sf.jabref.Globals;

// AboutPanel class
public class AboutPanel extends JComponent
{
  private Vector<TextBlock> textBlocks ;
  private String versionStr ;
  private String buildStr ;
  private AnimationThread thread;
  private ImageIcon image;


  // animated text positions
  public int TOP = 300 ; // offset from top - hide
  public int BOTTOM = 0 ; // show

  public int HEIGHT = 500 ;
  public int WIDTH = 500 ;

  private int borders[] ;  // Border-Coordinates of paintarea (xLeft, xRight, yTop, yBottom)
  private int paintWidth ;

  private Font font1 ;
  private Font font2 ;
  private Font font3 ;

  private AnimationListener aniListener ;
  private ImageProducer iProducer ;

  AboutPanel()
  {
    Font font = loadFont("ASTROLYT.TTF") ;
    font1 = font.deriveFont(Font.BOLD, (float) 14.0) ;
    font2 = font.deriveFont(Font.BOLD, (float) 20.0) ;

    font = loadFont("AUGIE.TTF") ;
    font3 = font.deriveFont(Font.BOLD, (float) 14.0) ;

    versionStr = "Version " + Globals.VERSION ;
    buildStr = " build " + Globals.BUILD ;

    image = new ImageIcon(getClass().getResource("/images/autumn.png"));

    HEIGHT = image.getIconHeight() ;
    WIDTH = image.getIconWidth() ;

    FontMetrics fm = getFontMetrics( font2 ) ;
    TOP = 2*fm.getHeight() ;
    fm = getFontMetrics( font1 ) ;
    BOTTOM = 2*fm.getHeight() ;

    borders = new int[4] ;
    borders[0] = 0 ;
    borders[1] = WIDTH ;
    borders[2] = TOP ;
    borders[3] = HEIGHT - TOP - BOTTOM ;


    paintWidth = borders[1] - borders[0] ;

    setForeground( Color.black) ;
    setBackground( Color.white) ;

    setBorder ( BorderFactory.createBevelBorder( BevelBorder.RAISED)) ;

    textBlocks = new Vector<TextBlock>( 50 ) ;

    loadAboutText() ;

    this.setDoubleBuffered(true);

    thread = new AnimationThread();
  }
// ----------------------------------------------------------------------------

  public void addAnimationListener(AnimationListener listener)
  {
    aniListener = listener ;
  }

// ----------------------------------------------------------------------------

  // returns
  private int getMiddleX(String text, Font font)
  {
    FontMetrics fm = getFontMetrics(font);
    return ( paintWidth/2 - ((fm.stringWidth(text) + 10) / 2)) ;
  }

// ----------------------------------------------------------------------------

  private Font loadFont(String fontName)
  {
    Font back = UIManager.getFont("Label.font") ;
    try
    {
      InputStream myStream = getClass().getResourceAsStream(GUIGlobals.fontPath + fontName) ;
      back = Font.createFont(Font.TRUETYPE_FONT, myStream) ;
    }
    catch (Exception e) { System.out.println(e) ; }

    return back ;
  }

// ----------------------------------------------------------------------------

  private final void loadAboutText()
  {
    TextBlock block = null ;
    AboutTextLine aLine = null ;

    int index = -3 ;
    FontMetrics fm = getFontMetrics(font3);
    try
    {
      InputStream stream = getClass().getResourceAsStream(GUIGlobals.getLocaleHelpPath() + "credits.txt" ) ;
      if (stream == null)
      {
        stream = getClass().getResourceAsStream( GUIGlobals.helpPre +
                                                 "credits.txt" ) ;
      }
      InputStreamReader reader = new InputStreamReader( stream ) ;
      BufferedReader input = new BufferedReader(reader, 1000) ;

      while ( input.ready() )
      {
        String line = input.readLine() ;

        if (line != null)
        {
          line = line.trim() ;

          if (line.length() > 0)
          {
            if (line.charAt(0) == '#')  // new Block....
            {
              if (block != null)  //insert previous block
              {
                textBlocks.add(block) ;
                index+=2 ;
              }

              aLine = new AboutTextLine( line.substring(1).trim()) ;
              aLine.setTag(2);
              aLine.setPos(getMiddleX(aLine.getText(), font2), borders[0] -fm.getHeight()*(index+3)*1.5);
              aLine.setDirection(0.0, 1.0);
              aLine.setFont(font2);

              block = new TextBlock() ;
              block.setHeading(aLine);
              block.setVisible(true);

            }
            else  // Blocklines
            {
              aLine = new AboutTextLine( line.trim() ) ;
              aLine.setPos( getMiddleX( line, font3 ),
                            borders[3] + ( index * fm.getHeight() * 1.5 ) ) ;
              aLine.setTag( 10 ) ;
              aLine.setDirection( 0.0, -1.0 ) ;
              aLine.setFont( font3 ) ;

              block = new TextBlock() ;
              block.add( aLine ) ;
              block.setVisible(true);
              
              index++ ;
            }
          }
        }
      }
      input.close() ;
    }

    catch ( Exception e )
    {
      block = new TextBlock() ;
      block.setHeading( new AboutTextLine("failure") );
      String line = "no infos available" ;
      aLine = new AboutTextLine( line ) ;
      block.add( aLine ) ;
    }

    textBlocks.add(block);  // insert last block
  }

// ----------------------------------------------------------------------------

  public void paintComponent( Graphics g )
  {
    if (thread.mode == 0)
    {
      thread.start();
//      thread.setEnabled(true);
    }
    else
    if (thread.mode == 1)
    {
      image.paintIcon(this, g, 0, 0);

      FontMetrics fm = g.getFontMetrics( font1 ) ;

      int x1 = ( getWidth() - fm.stringWidth( versionStr ) ) / 2 ;
      int y1 = getHeight() - fm.getHeight() - 4 ;
      int y2 = getHeight() - 5 ;
/*
      int x1 = ( getWidth() - fm.stringWidth( versionStr ) ) / 2 ;
      int y1 = 4 ;
      int y2 = fm.getHeight() +4 ;
*/
      g.setFont( font1 ) ;

      g.setColor( Color.black ) ;
      g.drawString( versionStr, x1, y1 ) ;
      g.drawString( buildStr, x1, y2 ) ;

      g.setFont( font2) ;
      fm = g.getFontMetrics( font2 ) ;
      g.drawString( "JabRef", (getWidth() - fm.stringWidth("JabRef")) /2, fm.getHeight()+10) ;


      for ( TextBlock block : textBlocks){
        if (block.isVisible()) // only if Block is marked as visible
        {
          // print Heading
          AboutTextLine head = block.getHeading() ;
          drawLine(head, g) ;

          for (AboutTextLine line : block){
            drawLine(line, g) ;
          }
        }
      }
    }
    else
    {
      image.paintIcon(this, g, 0, 0);
    }
  }
// ----------------------------------------------------------------------------

  private void drawLine(AboutTextLine line, Graphics g)
  {
    int x = line.getPosX() ;
    int y = line.getPosY() ;
    if ( ( x > borders[0] - 10 ) && ( x < borders[1] + 10 ) &&
         ( y > borders[2] - 10 ) && ( y < borders[3] + 10 ) )
    {
      if ( line.getVisible() )
      {
        g.setFont( line.getFont() ) ;
        g.setColor( line.getColor() ) ;
        g.drawString( line.getText(), line.getPosX(), line.getPosY() ) ;
      }
    }
  }
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------

  public Dimension getPreferredSize()
  {
    return new Dimension( WIDTH, HEIGHT ) ;
  }

  public void removeNotify()
  {
    super.removeNotify();
    thread.kill();
  }

  public void skipAnimation()
  {
    thread.kill() ;
    if (aniListener != null) aniListener.animationReady();
  }

// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------

  class AnimationThread extends Thread
  {
    private boolean running = true ;
    private double help01 = 1.0 ;
    private int mode = 0 ;
    public int sleepTime = 50 ;
    private int zone2Counter = 0 ;
    private boolean runMode = true ;

    AnimationThread()
    {
      super( "About box animation thread" ) ;
      setPriority( Thread.MIN_PRIORITY ) ;
    }

    public void kill()
    {
      running = false ;
    }

    public void setEnabled(boolean onOff) { runMode = onOff ; }

    public synchronized void setMode(int newMode) { mode = newMode ; }

    public void run()
    {
      Object mutex = new Object() ;

      mode = 1 ;
      runMode = true ;
      while ( running )
      {

        synchronized(mutex)
        {
          try
          {
            do
            {
              mutex.wait( sleepTime ) ;
            } while (!runMode) ;
          }
          catch ( Exception e )
          {
          }
        }
        if (mode == 1)  // Textanimation
        {
          int counter = 0 ;

          for ( Enumeration<TextBlock> myE = textBlocks.elements() ; myE.hasMoreElements() ; )
          {
            TextBlock block = myE.nextElement() ;
            AboutTextLine head = block.getHeading() ;
            counter = performStep(head) ;

            for (AboutTextLine line : block){
            	counter += performStep( line ) ;
            }
          }
          if (counter < 1)
          {
            mode = 2 ;
          }
          repaint(borders[0]-10, borders[2]-10, borders[1]+10, borders[3]+10) ;
        }
        else if (mode == 2)  // Picture animation
        {
          if (sleepTime < 2)
            sleepTime = 5 ;
          else
            sleepTime -= sleepTime / 3 ;

          image.setImage( createImage( iProducer) );
          repaint(0, 0, WIDTH, HEIGHT) ;
        }
      }
    }

    private int performStep(AboutTextLine line)
    {
      int back = 0 ;

      line.performTimeStep( 1.0 ) ;

      if ( line.getTag() == 2 )  // Heading
      {
        int zone = (int) (HEIGHT / 3.5) ;
        if ( line.getPosY() > zone )
        {
          line.setSpeed( 0.0 ) ;
          line.setTag( 4 ) ;
          zone2Counter = 0 ;
        } else
        if ( line.getPosY() > ( zone - 10) )
        {
          zone2Counter=1 ;
        }
        back++ ;
      }
      else if ( line.getTag() == 4) // Heading Blender
      {
        if (zone2Counter < 1)
        {
          Color col = line.getColor() ;
          int rgb = col.getRGB() + 1023 ;
          line.setColor( new Color( rgb ) ) ;
        }
        else
        {
          line.setVisible(false);
          line.setTag(5);
        }
      }
      else if ( line.getTag() == 10 )  // scrolling text
      {
        if ( line.getPosY() < ( HEIGHT / 3 ) )
        {
          line.setDirection( help01, 0.0 ) ;
          line.setAccel( 0.5 ) ;
          line.setTag( 11 ) ;
          help01 = help01 * -1.0 ;
        }
        back = 1 ;
      }
      else if (line.getTag() == 11) // text line out
      {
         if ((line.getPosX() < -100) || (line.getPosX() > WIDTH+100))
         {
           line.setTag(12);
           line.setVisible(false);
         }
         back = 1 ;
      }

      return back ;
    }
  }

}
