# vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright (c) 2011 Grid Dynamics Consulting Services, Inc, All Rights Reserved
#  http://www.griddynamics.com
#
#    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
#
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
#  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
#  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
#  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
#  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
#  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
#  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from nova_billing import vm_states

BILLABLE_PARAMS_WEIGHTS = {
    'local_gb' : 1,
     'memory_mb' : 2,
     'vcpus' : 3
}

class BasePriceCalculator(object):
    price = 1

    def calculate(self, period_start, period_stop, local_gb=None, memory_mb=None, vcpus=None):
        return (period_stop - period_start).seconds * self.price


class ActivePriceCalculator(BasePriceCalculator):
    def calculate(self, period_start, period_stop, local_gb, memory_mb, vcpus):
        self.price += BILLABLE_PARAMS_WEIGHTS['local_gb'] * local_gb
        self.price += BILLABLE_PARAMS_WEIGHTS['memory_mb'] * memory_mb
        self.price += BILLABLE_PARAMS_WEIGHTS['vcpus'] * vcpus
        return super(ActivePriceCalculator, self).calculate(period_start, period_stop)


class SegmentPriceCalculator(object):
    calculators = {}

    def __init__(self):
        self.calculators[vm_states.ACTIVE] = ActivePriceCalculator()
        self.calculators['DEFAULT'] = BasePriceCalculator()

    def calculate(self, period_start, period_stop, state,
                  local_gb, memory_mb, vcpus):
        if self.calculators.has_key(state):
            return self.calculators[state].calculate(period_start,
                period_stop, local_gb, memory_mb, vcpus)
        else:
            return self.calculators['DEFAULT'].calculate(period_start, period_stop,
                local_gb, memory_mb, vcpus)

@@ -1497,15 +1497,23 @@
 rt).
+total_
 seconds
+()
  * s
@@ -1957,14 +1957,16 @@
 ss S
-egment
+uspended
 Pric
@@ -1981,29 +1981,46 @@
 tor(
-object
+BasePriceCalculator
 ):%0A    
+def 
 calculat
 ors 
@@ -2019,93 +2019,242 @@
 ulat
-ors = %7B%7D%0A%0A    def __init__(self):%0A        self.calculators%5Bvm_states.ACTIVE%5D = Active
+e(self, period_start, period_stop, local_gb, memory_mb, vcpus):%0A        self.price += BILLABLE_PARAMS_WEIGHTS%5B'local_gb'%5D * local_gb%0A        self.price += BILLABLE_PARAMS_WEIGHTS%5B'memory_mb'%5D * memory_mb%0A        return super(Suspended
 Pric
@@ -2268,23 +2268,15 @@
 ator
-()%0A       
+,
  self
+)
 .cal
@@ -2284,25 +2284,68 @@
 ulat
-ors%5B'DEFAULT'%5D = 
+e(period_start, period_stop)%0A%0A%0Aclass StoppedPriceCalculator(
 Base
@@ -2363,11 +2363,10 @@
 ator
-()%0A
+):
 %0A   
@@ -2417,33 +2417,8 @@
 op, 
-state,%0A                  
 loca
@@ -2431,32 +2431,275 @@
 memory_mb, vcpus
+):%0A        self.price += BILLABLE_PARAMS_WEIGHTS%5B'local_gb'%5D * local_gb%0A        return super(StoppedPriceCalculator, self).calculate(period_start, period_stop)%0A%0A%0Aclass SegmentPriceCalculator(object):%0A    calculators = %7B%7D%0A%0A    def __init__(self
 ):%0A        if se
@@ -2697,11 +2697,8 @@
     
-if 
 self
@@ -2713,43 +2713,135 @@
 tors
-.has_key(state):%0A            return
+%5Bvm_states.ACTIVE%5D = ActivePriceCalculator()%0A        self.calculators%5Bvm_states.SUSPENDED%5D = SuspendedPriceCalculator()%0A       
  sel
@@ -2858,67 +2858,264 @@
 ors%5B
+vm_
 state
-%5D.calculate(period_start,%0A                period_stop,
+s.PAUSED%5D = SuspendedPriceCalculator()%0A        self.calculators%5Bvm_states.STOPPED%5D = SuspendedPriceCalculator()%0A        self.calculators%5B'DEFAULT'%5D = BasePriceCalculator()%0A%0A    def calculate(self, period_start, period_stop, state,%0A                 
  loc
@@ -3138,16 +3138,17 @@
 , vcpus)
+:
 %0A       
@@ -3152,32 +3152,42 @@
     
-else:%0A            return
+calc = self.calculators.get(state,
  sel
@@ -3210,16 +3210,37 @@
 EFAULT'%5D
+)%0A        return calc
 .calcula
@@ -3268,32 +3268,16 @@
 od_stop,
-%0A               
  local_g

Implement price calculators for VMs states