from orangescape.model.engine.exception.Error import FormulaArgumentError
from orangescape.model.engine.exception.ErrorMessage import Engine1001,Engine1004
from orangescape.model.engine.operation.function import functions
from orangescape.model.server.util.metadatautil import getFormula

def getFormulaDetails(node):
    formula = getFormula(node)
    if formula:
        cell = formula.getCellMetadata()
        if cell:
            cellDisplayName = cell.getCellDisplayName()
            sheetName = cell.getRowMetadata().getSheetMetadata().getSheetName()
            return ' In the cell %s (%s)'%(cellDisplayName, sheetName)
    return ''

def validateOperand(node, opList):
    functionName = node.getNodeValue()
    isFunctionImplemented = functions.get(functionName)
    if not isFunctionImplemented:
        raise Exception("Function '%s' is not implemented"%(functionName))
    funcDict = functions[functionName]
    function = funcDict['Name']
    minarg = funcDict['Min_Arg']
    maxarg = funcDict['Max_Arg']
    opTypeList = funcDict['OperandTypeList']
    category = funcDict['Category']

    # Used in Functions UnitTestcase(FunctionTest.py) [May be Removed in Future] >>Starts Here<<
    if functionName in ("XIRR","XNPV"):
        for index,operand in enumerate(opList):
            input = eval(str(operand))
            opList[index] = input
        return category
    # >> Ends Here <<

    operandsListLength = len(opList)
    if operandsListLength < minarg:
        raise FormulaArgumentError, Engine1001 % (minarg,operandsListLength,functionName+getFormulaDetails(node))
    elif maxarg > 0 and operandsListLength > maxarg:
        raise FormulaArgumentError, Engine1001 % (maxarg,operandsListLength,functionName+getFormulaDetails(node))

    opTypeListLength = len(opTypeList)
    for index,operand in enumerate(opList):
        if index > (opTypeListLength-1) and maxarg < 0:
            opType = opTypeList[opTypeListLength-1]
        else:
            opType = opTypeList[index]

        if "NUMBER" == opType:
            try:
                opList[index] = getNumber(operand)
            except (ValueError,TypeError), e:
                raise FormulaArgumentError,Engine1004%(index+1, opType, operand, functionName+getFormulaDetails(node))
        elif "TEXT" == opType:
            opList[index] = getString(operand)
        elif "ANY" == opType:
            pass
    return category

def getString(arg):
    if type(arg) is float and (arg - int(arg)) == 0.0:
        return "%d"%(arg)
    return str(arg or "")

def getNumber(arg):
    return float(arg or 0.0)

def getInteger(arg):
    return int(arg or 0)

def getConvertedNumber(value):
    try:
        return float(value)
    except (ValueError,TypeError),e:
        if value=='TRUE':
            return 1.0
        elif value=='FALSE':
            return 0.0
        else:
            return None
