/////////////////////////////////////////////////////////////////////////
//
// © University of Southampton IT Innovation Centre, 2004
//
// Copyright in this library belongs to the IT Innovation Centre of
// 2 Venture Road, Chilworth Science Park, Southampton, SO16 7NP, UK.
//
// This software may not be used, sold, licensed, transferred, copied
// or reproduced in whole or in part in any manner or form or in or
// on any media by any person other than in accordance with the terms
// of the Licence Agreement supplied with the software, or otherwise
// without the prior written consent of the copyright owners.
//
// This software is distributed WITHOUT ANY WARRANTY, without even the
// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE, except where stated in the Licence Agreement supplied with
// the software.
//
//      Created by:             Stuart E. Middleton
//      Created date:           2004/04/30
//      Created for project:    GEMSS
//
/////////////////////////////////////////////////////////////////////////
//
//      Dependencies: None
//
/////////////////////////////////////////////////////////////////////////
//
//      Last commit info:       $Author: $
//                              $Date: $
//                              $Revision: $
//
/////////////////////////////////////////////////////////////////////////

package uk.ac.soton.itinnovation.gemss.business;

import java.lang.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.*;
import java.io.*;

import uk.ac.soton.itinnovation.gemss.business.PriceModel;
import uk.ac.soton.itinnovation.gemss.negotiation.wsla.WSLAQoSHandler;
import uk.ac.soton.itinnovation.gemss.negotiation.wsla.WSLAQoSHandlerImpl;

/**
 * Server side business module to handle pricing. A price model simply takes in a WSLA and
 * calculates a price for it. This class encodes a dynamic pricing model based on exec time
 * and dynamic server availability.
 */
public class DynamicPriceModel extends PriceModel {

      // memebr vars
      private String mstrStartTimeURI;
      private String mstrEndTimeURI;
      private String mstrPriceURI;
      private String mstrEuros;
      private WSLAQoSHandler mwslaHandler;

      // logging
      private static Logger mlogger = Logger.getLogger("uk.ac.soton.itinnovation.gemss.business.DynamicPriceModel");

      /**
       * inits any variables and reads the config file. A config file would typically contain the
       * property names (ontology URI's), units and value types of all the QoS properties that
       * affect the price within the implementing pricing model.
       */
      public DynamicPriceModel( String strWSLAHandlerConfig, String strStartTimeURI, String strEndTimeURI, String strPriceURI ) throws Exception
      {
            // read config file
            // TODO change args to be a simple config file
            // wsla handler config filename
            // start time URI
            // end time URI
            // known currency units (euros URI)
            mstrStartTimeURI = strStartTimeURI;
            mstrEndTimeURI = strEndTimeURI;
            mstrPriceURI = strPriceURI;
            mstrEuros = "http://www.it-innovation.soton.ac.uk/ontology/gemss-qos-ontology#EuroUnit";

            // make WSLA handler object
            mwslaHandler = new WSLAQoSHandlerImpl( strWSLAHandlerConfig );
      }

      /**
       * calculates the price of a WSLA according to the pricing model's criertia. The price unit used is defined within the WSLA
       * and a conversion will take place if the price model unit's are different. If the WSLA unit is unknown then -1 will be
       * returned since no conversion is possible.
       * @param strWSLA string representation of a WSLA
       * @return price in the unit used by the WSLA
       */
      public double calculatePrice( String strWSLA ) throws Exception
      {
            Hashtable hashValues;
            Vector vectorProp;
            String strWSLAPriceUnit, strDate;
            long nStart, nEnd;
            double nPrice;

            try {
                  // parse WSLA
                  // hash = [prop name, vector(unit uri, type uri, value)]
                  hashValues = mwslaHandler.parseSLAParameters( strWSLA );
                  if( hashValues == null ) throw new Exception("WSLA parse failed");

                  // get price property vector and WSLA unit
                  vectorProp = (Vector) hashValues.get( mstrPriceURI );
                  strWSLAPriceUnit = (String) vectorProp.elementAt(0);

                  // no conversions supported (!)
                  if( !mstrEuros.equals( strWSLAPriceUnit ) ) {
                        mlogger.log( Level.WARNING,"Price conversion NOT supported fot unit "+strWSLAPriceUnit+", can only use "+mstrEuros );
                        return -1;
                  }

                  // get start and end time
                  vectorProp = (Vector) hashValues.get( mstrStartTimeURI );
                  strDate = (String) vectorProp.elementAt(2);
                  nStart = Long.parseLong( strDate );

                  vectorProp = (Vector) hashValues.get( mstrEndTimeURI );
                  strDate = (String) vectorProp.elementAt(2);
                  nEnd = Long.parseLong( strDate );

                  // calc price
                  if( nStart != -1 && nEnd != -1 ) {
                        nPrice = 1.0 * ( nEnd - nStart ) / 360000.0;
                  }
                  else nPrice = 1.0;

                  // TODO remove this line of code - adds random value to force testing bid value differences
                  nPrice += Math.random();
                  // End test code

                  return nPrice;
            }
            catch( Exception ex ) {
                  mlogger.log( Level.SEVERE,"calculate price failed",ex );
                  return -1;
            }
      }

} // end of PriceModel
