/*
 * Copyright (c) 2014 by the original author
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.powertac.common;

import org.apache.log4j.Logger;

/**
 * Represents available regulation capacity for a given TariffSubscription.
 * This is basically a data structure that holds two numbers: an amount of
 * up-regulation capacity (non-negative), and an amount of down-regulation
 * capacity (non-positive).
 * 
 * @author John Collins
 */
public class RegulationCapacity
{
  protected static Logger log = Logger.getLogger(RegulationCapacity.class.getName());

  // ignore small numbers
  private static double epsilon = 1e-4;

  private double upRegulationCapacity = 0.0;

  private double downRegulationCapacity = 0.0;

  /**
   * Creates a new RegulationCapacity instance specifying the amounts of
   * regulating capacity available for up-regulation and down-regulation.
   * Values are expressed with respect to the balancing market; a negative
   * value means power is delivered to the customer (down-regulation), and a
   * positive value means power is delivered to the balancing market
   * (up-regulation).
   */
  public RegulationCapacity (double upRegulationCapacity,
                             double downRegulationCapacity)
  {
    super();
    if (upRegulationCapacity < 0.0) {
      log.warn("upRegulationCapacity " + upRegulationCapacity + " < 0.0");
      upRegulationCapacity = 0.0;
    }
    if (downRegulationCapacity > 0.0) {
      log.warn("downRegulationCapacity " + downRegulationCapacity + " > 0.0");
      downRegulationCapacity = 0.0;
    }
    this.upRegulationCapacity = upRegulationCapacity;
    this.downRegulationCapacity = downRegulationCapacity;
  }

  /**
   * Returns the available up-regulation capacity in kWh.
   * Value is non-negative.
   */
  public double getUpRegulationCapacity ()
  {
    return upRegulationCapacity;
  }

  /**
   * Sets the up-regulation value.
   * Argument must be non-negative.
   */
  public void setUpRegulationCapacity (double value)
  {
    double filteredValue = filterValue(value);
    if (filteredValue < 0.0) {
      log.warn("Attempt to set negative up-regulation capacity "
               + filteredValue);
      return;
    }
    upRegulationCapacity = filteredValue;
  }

  /**
   * Returns the available down-regulation capacity in kWh.
   * Value is non-positive.
   */
  public double getDownRegulationCapacity ()
  {
    return downRegulationCapacity;
  }

  /**
   * Sets the down-regulation value.
   * Argument must be non-negative.
   */
  public void setDownRegulationCapacity (double value)
  {
    double filteredValue = filterValue(value);
    if (filteredValue > 0.0) {
      log.warn("Attempt to set positive down-regulation capacity " + filteredValue);
      return;
    }
    downRegulationCapacity = filteredValue;
  }

  /**
   * Adds the capacities in the given RegulationCapacity instance to this
   * instance. 
   */
  public void add (RegulationCapacity rc)
  {
    upRegulationCapacity += rc.upRegulationCapacity;
    downRegulationCapacity += rc.downRegulationCapacity;
  }

  /**
   * Adds the given amount of up-regulation capacity.
   * Amount must be non-negative.
   */
  public void addUpRegulation (double amount)
  {
    if (amount < 0.0) {
      log.warn("Attempt to add negative up-regulation capacity " + amount);
      return;
    }
    upRegulationCapacity += amount;
  }

  /**
   * Adds the given amount of down-regulation capacity.
   * Amount must be non-positive.
   */
  public void addDownRegulation (double amount)
  {
    if (amount > 0.0) {
      log.warn("Attempt to add positive down-regulation capacity " + amount);
      return;
    }
    downRegulationCapacity += amount;
  }

  // filter out small values
  private double filterValue (double original)
  {
    if (Math.abs(original) < epsilon)
      return 0.0;
    return original;

  }
}

@@ -660,16 +660,103 @@
 .Logger;
+%0Aimport org.powertac.common.state.Domain;%0Aimport org.powertac.common.state.StateChange;
 %0A%0A/**%0A *
@@ -1039,16 +1039,24 @@
 ins%0A */%0A
+@Domain%0A
 public c
@@ -1168,16 +1168,53 @@
 me());%0A%0A
+  long id = IdGenerator.createId();%0A%0A
   // ign
@@ -2326,32 +2326,79 @@
 nCapacity;%0A  %7D%0A%0A
+  public long getId ()%0A  %7B%0A    return id;%0A  %7D%0A%0A
   /**%0A   * Retur
@@ -2639,32 +2639,47 @@
 negative.%0A   */%0A
+  @StateChange%0A
   public void se
@@ -3228,32 +3228,47 @@
 negative.%0A   */%0A
+  @StateChange%0A
   public void se
@@ -3690,24 +3690,48 @@
 rc)%0A  %7B%0A    
+setUpRegulationCapacity(
 upRegulation
@@ -3736,25 +3736,24 @@
 onCapacity +
-=
  rc.upRegula
@@ -3764,22 +3764,49 @@
 Capacity
+)
 ;%0A    
+setDownRegulationCapacity(
 downRegu
@@ -3821,17 +3821,16 @@
 pacity +
-=
  rc.down
@@ -3839,32 +3839,33 @@
 gulationCapacity
+)
 ;%0A  %7D%0A%0A  /**%0A   
@@ -4121,32 +4121,56 @@
 turn;%0A    %7D%0A    
+setUpRegulationCapacity(
 upRegulationCapa
@@ -4171,32 +4171,32 @@
 onCapacity +
-=
  amount
+)
 ;%0A  %7D%0A%0A  /**
@@ -4462,32 +4462,58 @@
 turn;%0A    %7D%0A    
+setDownRegulationCapacity(
 downRegulationCa
@@ -4524,16 +4524,16 @@
 ty +
-=
  amount
+)
 ;%0A  

make RegulationCapacity be a domain type