package org.ourfilesystem.simpleui;

/*
OurFileSystem is a peer2peer file sharing program.
Copyright (C) 2012  Robert Gass

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.

*/

import java.awt.Component;
import java.awt.EventQueue;
import java.io.File;
import java.util.HashMap;
import java.util.LinkedList;

import javax.swing.JProgressBar;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;

import org.ourfilesystem.filehander.FileReturnInterface;
import org.ourfilesystem.utilities.HumReadFileSize;

public class DownloadsTableModel extends AbstractTableModel implements FileReturnInterface {
	private static final long serialVersionUID = 1L;

	private LinkedList<DLRow> Rows;
	private HashMap<File, DLRow> Map;
	
	private String columns[] = {
			"File",
			"Digest",
			"Total Size",
			"Progress",
			"Pending",
			"Priority",
			"Paused"
	};
	
	@SuppressWarnings("rawtypes")
	private Class classes[] = {
			String.class,
			String.class,
			String.class,
			DLRow.class,
			Integer.class,
			Integer.class,
			Boolean.class
	};
	
	public class ProgressCellRenderer extends JProgressBar implements TableCellRenderer {
		private static final long serialVersionUID = 1L;

		@Override
		public Component getTableCellRendererComponent(JTable arg0,	Object arg1, boolean arg2, boolean arg3, int arg4, int arg5) {
			if (arg1 instanceof DLRow) {
				DLRow dl = (DLRow)arg1;
				if (dl.AmountComplete == 0) {
					setIndeterminate(true);
				}
				else {
					int tot = (int)(dl.TotalSize / (1024L * 1024L));
					int prg = (int)(dl.AmountComplete / (1024L * 1024L));
					setMaximum(tot);
					setValue(prg);
					setIndeterminate(false);
				}
				return this;
			}
			return null;
		}
		
	}
	
	public class DLRow {
		public File SaveAs;
		public String Dig;
		public long TotalSize;
		public long AmountComplete;
		public int Pending;
		public boolean Paused;
		public boolean InProgress;
		public int Priority;
		public DLRow(File saveas,
					 String dig,
					 long totalsize,
					 long amountcomplete,
					 int pending,
					 boolean paused,
					 boolean inprogress,
					 int priority) {
			update(saveas, dig, totalsize,amountcomplete,pending,paused,inprogress,priority);
		}
		public void update(File saveas,
					 String dig,
					 long totalsize,
					 long amountcomplete,
					 int pending,
					 boolean paused,
					 boolean inprogress,
					 int priority) {
			SaveAs = saveas;
			Dig = dig;
			TotalSize = totalsize;
			AmountComplete = amountcomplete;
			Pending = pending;
			Paused = paused;
			InProgress = inprogress;
			Priority = priority;
		}
	}
	
	public DownloadsTableModel() {
		Rows = new LinkedList<DLRow>();
		Map = new HashMap<File, DLRow>();
	}
	
	public String getColumnName(int col) {
		return columns[col];
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public Class getColumnClass(int col) {
		return classes[col];
	}
	
	@Override
	public int getColumnCount() {
		return columns.length;
	}

	@Override
	public synchronized int getRowCount() {
		return Rows.size();
	}
	
	public synchronized DLRow getRow(int row) {
		if (row < Rows.size()) {
			return Rows.get(row);
		}
		return null;
	}

	@Override
	public synchronized Object getValueAt(int row, int col) {
		DLRow r = getRow(row);
		if (r != null) {
			if (col == 0) {
				return r.SaveAs.getName();
			}
			else if (col == 1) {
				return r.Dig;
			}
			else if (col == 2) {
				return HumReadFileSize.fileSize(r.TotalSize);
			}
			else if (col == 3) {
				return r;
			}
			else if (col == 4) {
				return r.Pending;
			}
			else if (col == 5) {
				return r.Priority;
			}
			else if (col == 6) {
				return r.Paused;
			}
		}
		return null;
	}
	
	public synchronized void removeFile(File f) {
		DLRow dl = Map.get(f);
		Map.remove(f);
		for (int cnt = 0; cnt < Rows.size(); cnt++) {
			if (dl == Rows.get(cnt)) {
				Rows.remove(cnt);
				fireTableRowsDeleted(cnt, cnt);
			}
		}
	}

	private synchronized void doStatusUpdate(final File saveas, 
									 final String dig,
									 final long totalsize,
									 final long amountcomplete, 
									 final int pending,
									 final boolean paused, 
									 final boolean inprogress,
									 final int priority) {
		DLRow r = Map.get(saveas);
		if (r == null) {
			r = new DLRow(saveas, dig, totalsize, amountcomplete, pending, paused, inprogress, priority);
			Map.put(saveas, r);
			Rows.add(r);
			fireTableRowsInserted(Rows.size()-1, Rows.size()-1);
		}
		else {
			r.update(saveas, dig, totalsize, amountcomplete, pending, paused, inprogress, priority);
			for (int cnt = 0; cnt < Rows.size(); cnt++) {
				if (r == Rows.get(cnt)) {
					fireTableRowsUpdated(cnt, cnt);					
				}
			}
		}
	}
	
	public synchronized void clearAll() {
		Rows.clear();
		Map.clear();
		fireTableDataChanged();
	}
	
	@Override
	public synchronized void downloadStatusUpdate(final File saveas, 
									 final String dig,
									 final long totalsize,
									 final long amountcomplete, 
									 final int pending,
									 final boolean paused, 
									 final boolean inprogress,
									 final int priority) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				doStatusUpdate(saveas, dig, totalsize, amountcomplete, pending, paused, inprogress, priority);
			}
		});		
	}

}
