// created: 23.11.00
// modified: 29.12.00

import java.io.*;
import java.net.*;
import java.util.*;
import java.awt.*;
import javax.swing.*;

/******************/
/* class PagePref */
/******************/
  
public class PagePref
 {

 MultiAttributeValueFunction theFunction = null;
 Vector thePages = new Vector(0);  //the vector contains WebPage objects
 float maxValue = 0.0f;  // needed to normalise the values
 int maxAmountText = 0;
 int maxNumImages = 0;
 int maxNumTables = 0;
 int maxNumLinks = 0;
 int maxNumAllDownloads = 0;
 int maxNumOtherDownloads = 0;
 int maxNumImageDownloads = 0;
 int maxNumSoundDownloads = 0;
 int maxNumVideoDownloads = 0;

 /***************/
 /* constructor */
 /***************/

 public PagePref()
  {
  ValueFunction [] funcs = new ValueFunction [7];
  funcs[0] = new PositiveValueFunction(); //text
  funcs[1] = new PositiveValueFunction(); //images
  funcs[2] = new PositiveValueFunction(); //tables
  funcs[3] = new PositiveValueFunction(); //links
  funcs[4] = new CountChoiceValueFunction(); //downloads
  funcs[5] = new SomeValueFunction(); //frames
  funcs[6] = new ChoiceValueFunction(); //extension

  theFunction = new MultiAttributeValueFunction(funcs);
  }

 public PagePref(String [] locations)
  {
  this();
  setPages(locations);
  }

 /*********************/
 /* method parsePages */
 /***************************************************************************/
 /* calls the parse method on each page in turn, and sets the maxAttributes */
 /***************************************************************************/

 void parsePages()
  {
  // reset maximum attrubute values
  maxAmountText = 0;
  maxNumImages = 0;
  maxNumTables = 0;
  maxNumLinks = 0;
  maxNumAllDownloads = 0;
  maxNumOtherDownloads = 0;
  maxNumImageDownloads = 0;
  maxNumSoundDownloads = 0;
  maxNumVideoDownloads = 0;

  // parse all pages
  for (int i=0; i<thePages.size(); i++)
   {
   WebPage page = (WebPage) thePages.elementAt(i);
   try
    {
    System.out.println("Parsing \""+page.getLocation()+"\"");
    page.parse();
    } 
   catch (IOException e)
    {
    System.out.println("-Cannot parse due to an IO error");
    }

   // store maximum attribute values
   if (page.getAmountText() > maxAmountText)
     maxAmountText = page.getAmountText();
   if (page.getNumImages() > maxNumImages)
     maxNumImages = page.getNumImages();
   if (page.getNumTables() > maxNumTables)
     maxNumTables = page.getNumTables();
   if (page.getNumLinks() > maxNumLinks)
     maxNumLinks = page.getNumLinks();
   if (page.getNumDownloads() > maxNumAllDownloads)
     maxNumAllDownloads = page.getNumDownloads();
   if (page.getNumOtherDownloads() > maxNumOtherDownloads)
     maxNumOtherDownloads = page.getNumOtherDownloads();
   if (page.getNumImageDownloads() > maxNumImageDownloads)
     maxNumImageDownloads = page.getNumImageDownloads();
   if (page.getNumSoundDownloads() > maxNumSoundDownloads)
     maxNumSoundDownloads = page.getNumSoundDownloads();
   if (page.getNumVideoDownloads() > maxNumVideoDownloads)
     maxNumVideoDownloads = page.getNumVideoDownloads();
   }

  // set all max attribute values in the relevant value functions
  ((CountValueFunction) theFunction.getValueFunction(1)).setMax(maxAmountText);
  ((CountValueFunction) theFunction.getValueFunction(2)).setMax(maxNumImages);
  ((CountValueFunction) theFunction.getValueFunction(3)).setMax(maxNumTables);
  ((CountValueFunction) theFunction.getValueFunction(4)).setMax(maxNumLinks);
  CountChoiceValueFunction func = (CountChoiceValueFunction) theFunction.getValueFunction(5);
  String theChoice = func.getChoice();
  if (theChoice.equals(""))
    func.setMax(maxNumAllDownloads);
  else if (theChoice.equals("other"))
    func.setMax(maxNumOtherDownloads);
  else if (theChoice.equals("image"))
    func.setMax(maxNumImageDownloads);
  else if (theChoice.equals("sound"))
    func.setMax(maxNumSoundDownloads);
  else if (theChoice.equals("video"))
    func.setMax(maxNumVideoDownloads);
  }

 /********************/
 /* method orderURLs */
 /**************************************************************************/
 /* orders the URLs according to their values as set by the value function */
 /**************************************************************************/
 
 void orderPages(int [] weights)
  {
  // reset maxValue
  maxValue = 0.0f;
  //set up the value function weights
  for (int n=0; n<weights.length; n++)
   {
   theFunction.setFunctionWeight(n+1,weights[n]);
   }
  //evaluate the pages
  for (int i=0; i<thePages.size(); i++)
   {
   WebPage page = (WebPage) thePages.elementAt(i);
   if (page.isParsed())  // if the page isn't parsed, don't do a thing
    {
    // create the attribute objects that the ValueFunctions (in MultiAttributeValueFunction) need
    Object [] atts = new Object [7];
    atts[0] = new Integer(page.getAmountText());
    atts[1] = new Integer(page.getNumImages());
    atts[2] = new Integer(page.getNumTables());
    atts[3] = new Integer(page.getNumLinks());
    String theChoice = ((CountChoiceValueFunction) theFunction.getValueFunction(5)).getChoice();
    Vector theVector = new Vector(2);
    if (theChoice.equals(""))
      {
      theVector.addElement("");
      theVector.addElement(new Integer(page.getNumDownloads()));
      }
    else if (theChoice.equals("other"))
      {
      theVector.addElement("other");  // this could be alternatively be set to "".
      theVector.addElement(new Integer(page.getNumOtherDownloads()));
      }
    else if (theChoice.equals("image"))
      {
      theVector.addElement("image");
      theVector.addElement(new Integer(page.getNumImageDownloads()));
      }
    else if (theChoice.equals("sound"))
      {
      theVector.addElement("sound");
      theVector.addElement(new Integer(page.getNumSoundDownloads()));
      }
    else if (theChoice.equals("video"))
      {
      theVector.addElement("video");
      theVector.addElement(new Integer(page.getNumVideoDownloads()));
      }
    atts[4] = theVector;
    atts[5] = new Boolean(page.hasFrames());
    atts[6] = new String(page.getExtension());
    
    /********/
    System.out.println("evaluating page "+String.valueOf(i+1));   
    /********/

    float val = theFunction.evaluate(atts);
    if (val > maxValue)
      maxValue = val;

    /********/
    System.out.println("final value given by function= "+String.valueOf(val));   
    /********/
 
    page.setValue(val);
  
    // look at the value of each page in turn to find correct place to insert the page
    for (int n=0; n<i; n++)
     {
     if (val > ((WebPage) thePages.elementAt(n)).getValue())
      {
      thePages.removeElementAt(i);
      thePages.insertElementAt(page,n); 
      break;
      }
     }
    }
   }

  // normalize the page values
  float scale = 100.0f; 
  if (maxValue > 0.0f)
    scale = scale/maxValue;
  else
    scale = 0.0f;

  for (int i=0; i<thePages.size(); i++)
   { 
   WebPage page = (WebPage) thePages.elementAt(i);
   page.setValue(page.getValue()*scale);
   }
  }

 /*******************/
 /* method setPages */
 /*************************************************************/
 /* instantiates the pages and stores them in thePages Vector */
 /*************************************************************/

 void setPages(WebPage [] pages)
  {
  thePages = new Vector(pages.length);
  for (int i=0; i<pages.length; i++)
   {
   thePages.addElement(pages[i]);  
   }
  }

 void setPages(String [] locations)
  {
  thePages = new Vector(locations.length);
  for (int i=0; i<locations.length; i++)
   {
   try
    {
    System.out.println("Setting page \""+locations[i]+"\"");
    WebPage page = new WebPage(locations[i]);
    thePages.addElement(page);
    }
   catch (MalformedURLException e)
    {
    System.out.println("-Cannot set as it is a bad URL");
    }
   }
  }

 /******************/
 /* method addPage */
 /************************************************************/
 /* instantiates a new page and stores it in thePages Vector */
 /************************************************************/

 void addPage(WebPage page)
  {
  thePages.addElement(page); 
  }

 void addPage(String location) throws MalformedURLException
  {
  WebPage page = new WebPage(location);
  thePages.addElement(page);
  }

 void removePage(int pageNumber)
  {
  if (pageNumber-1 < thePages.size())
   {
   thePages.removeElementAt(pageNumber-1);
   }
  }

 void removePage(String location)
  {
  for (int n=0; n<thePages.size(); n++)
   {
   WebPage page = (WebPage) thePages.elementAt(n);
   if (page.getLocation().equals(location))
    {
    thePages.removeElementAt(n);
    return;
    }
   }
  }

 void setValueFunction(String attribute, ValueFunction function)
  {
  if (attribute.equals("text"))  
   {
   CountValueFunction func = (CountValueFunction) function;
   func.setMax(maxAmountText);
   theFunction.setValueFunction(1,func);
   }
  else if (attribute.equals("images"))
   {
   CountValueFunction func = (CountValueFunction) function;
   func.setMax(maxNumImages);
   theFunction.setValueFunction(2,func);
   }
  else if (attribute.equals("tables"))
   {
   CountValueFunction func = (CountValueFunction) function;
   func.setMax(maxNumTables);
   theFunction.setValueFunction(3,func);
   }
  else if (attribute.equals("links"))
   {
   CountValueFunction func = (CountValueFunction) function;
   func.setMax(maxNumLinks);
   theFunction.setValueFunction(4,func);
   }
  else if (attribute.equals("downloads"))  
   {
   CountChoiceValueFunction func = (CountChoiceValueFunction) function;
   if (func.getChoice().equals(""))
     func.setMax(maxNumAllDownloads);
   else if (func.getChoice().equals("other"))
     func.setMax(maxNumOtherDownloads);
   else if (func.getChoice().equals("image"))
     func.setMax(maxNumImageDownloads);
   else if (func.getChoice().equals("sound"))
     func.setMax(maxNumSoundDownloads);
   else if (func.getChoice().equals("video"))
     func.setMax(maxNumVideoDownloads);
   theFunction.setValueFunction(5,func);
   }
  else if (attribute.equals("frames"))
   {
   theFunction.setValueFunction(6,(ExistValueFunction) function);
   }
  else if (attribute.equals("extension"))  
   {
   theFunction.setValueFunction(7,(ChoiceValueFunction) function);
   }
  }

 /***************/
 /* get methods */
 /***************/

 WebPage [] getPages()
  {
  WebPage [] thePageArray = new WebPage [thePages.size()];
  return ((WebPage []) thePages.toArray(new WebPage[0]));
  }

 String [] getLocations()
  {
  String [] theStringArray = new String [thePages.size()];
  for (int i=0; i<theStringArray.length; i++)
   {
   theStringArray[i] = ((WebPage) thePages.elementAt(i)).getLocation();
   }
  return (theStringArray);
  }
 
 WebPage getPage(int num)
  {
  if (num-1 < thePages.size())
    return (WebPage) thePages.elementAt(num-1);
  else
    return null;
  }

 }