/*
 * File    : CompletionItem.java
 * Created : 24 nov. 2003
 * By      : Olivier
 *
 * Copyright (C) 2004, 2005, 2006 Aelitis SAS, All rights Reserved
 *
 * 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.
 *
 * 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 ).
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * AELITIS, SAS au capital de 46,603.30 euros,
 * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
 */

package org.gudy.azureus2.ui.swt.views.tableitems.files;

import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;

import org.gudy.azureus2.core3.disk.DiskManager;
import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
import org.gudy.azureus2.core3.disk.DiskManagerPiece;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.peer.PEPeerManager;
import org.gudy.azureus2.core3.peer.PEPiece;
import org.gudy.azureus2.core3.util.SystemTime;
import org.gudy.azureus2.ui.swt.mainwindow.Colors;
import org.gudy.azureus2.ui.swt.mainwindow.SWTThread;
import org.gudy.azureus2.ui.swt.plugins.UISWTGraphic;
import org.gudy.azureus2.ui.swt.pluginsimpl.UISWTGraphicImpl;
import org.gudy.azureus2.ui.swt.views.table.TableCellSWT;
import org.gudy.azureus2.ui.swt.views.table.utils.CoreTableColumn;

import org.gudy.azureus2.plugins.ui.Graphic;
import org.gudy.azureus2.plugins.ui.tables.*;

/** Torrent Completion Level Graphic Cell for My Torrents.
 *
 * @author Olivier
 * @author TuxPaper (2004/Apr/17: modified to TableCellAdapter)
 */
public class ProgressGraphItem
       extends CoreTableColumn 
       implements TableCellAddedListener
{
  private static final int borderWidth = 1;

  /** Default Constructor */
  public ProgressGraphItem() {
    super("pieces", TableManager.TABLE_TORRENT_FILES);
    initializeAsGraphic(POSITION_LAST, 200);
    setMinWidth(100);
  }

  public void cellAdded(TableCell cell) {
    new Cell(cell);
  }

  private class Cell
          implements TableCellRefreshListener, TableCellDisposeListener
  {
    int lastPercentDone = 0;
    private long last_draw_time	= SystemTime.getCurrentTime();
    private boolean bNoRed = false;
    private boolean	was_running = false;

    public Cell(TableCell cell) {
      cell.setFillCell(true);
			cell.addListeners(this);
    }

    public void dispose(TableCell cell) {
    	Graphic graphic = cell.getGraphic();
    	if (graphic instanceof UISWTGraphic) {
      	final Image img = ((UISWTGraphic)graphic).getImage();
        if (img != null && !img.isDisposed())
          img.dispose();
    	}
    }



    public void refresh(TableCell cell) {
    	final DiskManagerFileInfo fileInfo = (DiskManagerFileInfo)cell.getDataSource();
      int percentDone = 0;
      if (fileInfo != null && fileInfo.getLength() != 0)
        percentDone = (int)((1000 * fileInfo.getDownloaded()) / fileInfo.getLength());
      
      cell.setSortValue(percentDone);

      //Compute bounds ...
      int newWidth = cell.getWidth();
      if (newWidth <= 0) {
        return;
      }
      final int newHeight = cell.getHeight();

      final int x1 = newWidth - borderWidth - 1;
      final int y1 = newHeight - borderWidth - 1;
      if (x1 < 10 || y1 < 3) {
        return;
      }

      final DiskManager			manager			= fileInfo.getDiskManager();

      	// we want to run through the image part once one the transition from with a disk manager (running)
      	// to without a disk manager (stopped) in order to clear the pieces view
      
		 
	  boolean	running	= manager != null;
	  
	  final boolean bImageBufferValid = (lastPercentDone == percentDone) &&
                                  cell.isValid() && bNoRed && running == was_running;
      
      if (bImageBufferValid) {
        return;
      }

      was_running	= running;
      
      lastPercentDone = percentDone;

      Image piecesImage = null;
      Graphic graphic = cell.getGraphic();
      if (graphic instanceof UISWTGraphic) {
      	piecesImage = ((UISWTGraphic)graphic).getImage();
      }

      if (piecesImage != null && !piecesImage.isDisposed())
        piecesImage.dispose();
      piecesImage = new Image(SWTThread.getInstance().getDisplay(),
                              newWidth, newHeight);

      final GC gcImage = new GC(piecesImage);

	  	// dm may be null if this is a skeleton file view
	  
      DownloadManager	download_manager = fileInfo.getDownloadManager();
      
      PEPeerManager	peer_manager = download_manager==null?null:download_manager.getPeerManager();
      
      PEPiece[]	pe_pieces = peer_manager==null?null:peer_manager.getPieces();
    	  
  	  final long now =SystemTime.getCurrentTime();
  	  
      if (fileInfo != null && manager != null ) {
    	   	  
        if (percentDone == 1000) {
          gcImage.setForeground(Colors.blues[Colors.BLUES_DARKEST]);
          gcImage.setBackground(Colors.blues[Colors.BLUES_DARKEST]);
          gcImage.fillRectangle(1, 1, newWidth - 2, newHeight - 2);
        } else {
        	final int firstPiece = fileInfo.getFirstPieceNumber();
        	final int nbPieces = fileInfo.getNbPieces();
       
        	final DiskManagerPiece[] dm_pieces = manager.getPieces();
       
          bNoRed = true;
          for (int i = 0; i < newWidth; i++) {
        	  final int a0 = (i * nbPieces) / newWidth;
            int a1 = ((i + 1) * nbPieces) / newWidth;
            if (a1 == a0)
              a1++;
            if (a1 > nbPieces && nbPieces != 0)
              a1 = nbPieces;
            int nbAvailable = 0;
            boolean written   = false;
            boolean partially_written = false;
            if (firstPiece >= 0) {
              for (int j = a0; j < a1; j++){
            	  final int this_index = j+firstPiece;
                
                final DiskManagerPiece	dm_piece = dm_pieces[this_index];
                
                if (dm_piece.isDone()) {
                  nbAvailable++;
                }
                
                if (written){
                  continue;
                }
                
                if ( pe_pieces != null ){
                	
                	PEPiece	pe_piece = pe_pieces[this_index];
                	
                	if ( pe_piece != null ){
                		
                		written = written || (pe_piece.getLastDownloadTime(now) + 500) > last_draw_time;
                	}
                }
                
                if ((!written) && (!partially_written)) {
                	final boolean[] blocks = dm_piece.getWritten();
    
                  if ( blocks != null ) {
                    for (int k = 0; k < blocks.length; k++){
                      if (blocks[k]){
                    	  partially_written = true;
                        break;
                      }
                    }
                  }
                }
    
              } // for j
            } else {
              nbAvailable = 1;
            }
    
            gcImage.setBackground(written ? Colors.red
                                          : partially_written ? Colors.grey 
                                                      : Colors.blues[(nbAvailable * Colors.BLUES_DARKEST) / (a1 - a0)]);
            gcImage.fillRectangle(i, 1, 1, newHeight - 2);
            if (written)
              bNoRed = false;
          }
          gcImage.setForeground(Colors.grey);
        }
      } else {
        gcImage.setForeground(Colors.grey);
      }
	  
	  if ( manager != null ){
		  
		  gcImage.drawRectangle(0, 0, newWidth - 1, newHeight - 1);
	  }

      gcImage.dispose();
      last_draw_time =now;

      if (cell instanceof TableCellSWT) {
      	((TableCellSWT)cell).setGraphic(piecesImage);
      } else {
      	cell.setGraphic(new UISWTGraphicImpl(piecesImage));
      }
    }
  }
}
