#!/usr/bin/python3

from enum import IntEnum

class Support(IntEnum):
    Free = 0
    Basic = 1
    Standard = 2
    Advanced = 3
    Premium = 4

class Upgrade(IntEnum):
    Noupgrade = 0
    Patches = 1
    Oneminor = 2
    Allminor = 3
    Onemajor = 4
    All = 5

glob_support_prices = [ 0, 20, 50, 125, 1000 ]
glob_support_hourly = [ 0, 250, 250, 200, 150 ]
glob_support_hours = [ 0, 0, 0, 0.5, 4 ]
glob_lic_maxmonths = [ 0, 6, 12, 24, 36 ]
glob_lic_upgrades = [ Upgrade.Noupgrade, Upgrade.Patches, Upgrade.Oneminor, Upgrade.Onemajor, Upgrade.All ]
glob_sizes = [ 100, 300, 1000, 3000, 10000, 30000, 65000 ]
glob_price_purchase = [ 100, 200, 350, 500, 700, 950, 1200 ]
glob_price_prolong = [ 50, 100, 150, 200, 250, 300, 300 ]
glob_price_saas = [ 100, 100, 100, 150, 150, 250, 250 ]
glob_price_saas_prolong = [ 0, 0, 0, 0, 0, 0, 0 ]
glob_price_seat_fixed = [ 0.67, 0.4, 0.27, 0.15, 0.08, 0.05, 0.03 ]
glob_price_seat_saas = [ 1.25, 1.0, 0.8, 0.5, 0.38, 0.26, 0.15 ]
glob_discounts = ( (0, 0, 0, 0), (30, 30, 10, 10), (40, 40, 15, 20), (50, 50, 20, 30) )
glob_discount_levels = [ 500, 3000, 10000 ]
glob_noeol_discount = 0.8
glob_messages = []

def devidx(devices):
    for idx, val in enumerate(glob_sizes):
        if devices < val:
            return idx
    return len(glob_sizes)-1

def get_init_price(new_purchase, saas, devices = 0):
    if new_purchase:
        if saas:
            return glob_price_saas[devidx(devices)]
        else:
            return glob_price_purchase[devidx(devices)]
    else:
        if saas:
            return glob_price_saas_prolong[devidx(devices)]
        else:
            return glob_price_prolong[devidx(devices)]

def get_timedev_price(saas, devices, months):
    tarray = glob_price_seat_fixed
    if saas:
        tarray = glob_price_seat_saas
    pindex = devidx(devices)
    mprice = devices * tarray[pindex]
    if pindex < len(tarray):
        if mprice > glob_sizes[pindex] * tarray[pindex+1]:
            mprice = glob_sizes[pindex] * tarray[pindex+1]
    return mprice*months

def get_support_prices(suplevel = Support.Free):
    if suplevel < Support.Free or suplevel > Support.Premium:
        return (0, 0, 0)
    return (glob_support_prices[suplevel], glob_support_hourly[suplevel], glob_support_hours[suplevel])

def get_discount_level(base_amount):
    for idx, val in enumerate(glob_discount_levels):
        if base_amount < val:
            return idx
    return len(glob_discount_levels)

def add_license_base(new_purchase = True, saas = False, devices = 1, months = 1, support = Support.Free, paywhole = True, bonus = 0):
    global glob_messages
    myprices = (get_init_price(new_purchase, saas, devices), get_timedev_price(saas, devices, months)) + get_support_prices(support)
    base_cost = myprices[0]
    glob_messages.append("New-purchase/saas/suplevel           : "+str(new_purchase)+" / "+str(saas)+" / "+str(support))
    glob_messages.append("Devices/months/one-time payment      : "+str(devices)+" / "+str(months)+" / "+str(paywhole))
    glob_messages.append("(base-cost) One-time purchase cost   : "+str(base_cost))
    glob_messages.append("(base-cost) Monthly device cost      : "+str(myprices[1]/months))
    glob_messages.append("(base-cost) Monthly support cost     : "+str(myprices[2]))
    if Support.Free == support:
        glob_messages.append("Discount "+str(glob_noeol_discount*100)+"% - WARNING: AS-IS license (no Security Patches, no EOL guarantee), only one-time payment possible.")
    if paywhole:
        base_cost += myprices[1]
    else:
        base_cost += myprices[1]/months
    base_cost += myprices[2]
    monthly_base_cost = myprices[2]
    if not paywhole:
        monthly_base_cost += myprices[1]/months
    glob_messages.append("(base-cost) Total / Carry-over bonus : "+str(base_cost)+" / "+str(bonus))
    discount_lev = get_discount_level(base_cost + bonus)
    glob_messages.append("Discount tier / discounts            : "+str(discount_lev)+" / "+str(glob_discounts[discount_lev]))
    monthly_payment = myprices[2] * (100-glob_discounts[discount_lev][3]) / 100
    first_payment = myprices[0] * (100-glob_discounts[discount_lev][0]) / 100 + monthly_payment
    if paywhole:
        first_payment += myprices[1] * (100-glob_discounts[discount_lev][1]) / 100
    else:
        mpf = myprices[1]/months * (100-glob_discounts[discount_lev][1]) / 100
        first_payment += mpf
        monthly_payment += mpf
    if Support.Free == support:
        first_payment *= (1-glob_noeol_discount)
    total = first_payment + (months-1) * monthly_payment
    glob_messages.append("Initial / monthly / total / TC/dev/m : "+str(first_payment)+" / "+str(monthly_payment)+" / "+str(total)+" / "+"{:.3f}".format(total/months/devices))
    return glob_messages
