import xml.etree.ElementTree as ET


class MCConfig(object):
    """ Memory Controller Configuration Class

        The format used in memory specification XML files differs from the
        format used in memory controller configuration XML files. Each class
        uses the proper format when searching for elements.
    """
    def getValue(self, id):
        return self.xmlMCConfig.findall(id)[0].attrib['value']

    def getIntValue(self, id):
        return int(self.getValue(id))

    def __init__(self, dbconnection):
        cursor = dbconnection.cursor()
        cursor.execute("SELECT MCconfig FROM GeneralInfo")
        result = cursor.fetchone()
        self.xmlMCConfig = ET.parse(result[0])


class MemSpec(object):
    """ Memory Specification Class

        The format used in memory specification XML files differs from the
        format used in memory configuration XML files. Each class uses the
        proper format when searching for elements.
    """
    def getValue(self, id):
        match = ".//parameter[@id='{0}']".format(id)
        val = self.xmlMemSpec.findall(match)[0].attrib['value']
        return val

    def getIntValue(self, id):
        return int(self.getValue(id))

    def __init__(self, dbconnection):
        cursor = dbconnection.cursor()
        cursor.execute("SELECT Memspec FROM GeneralInfo")
        result = cursor.fetchone()
        self.xmlMemSpec = ET.parse(result[0])


def getClock(dbconnection):
    cursor = dbconnection.cursor()
    cursor.execute("SELECT clk, UnitOfTime FROM GeneralInfo")
    clock, unit = cursor.fetchone()
    return (clock, unit)


def getNumberOfBanks(dbconnection):
    cursor = dbconnection.cursor()
    cursor.execute("SELECT NumberOfBanks FROM generalInfo")
    result = cursor.fetchone()
    return result[0]


def getWindowSize(connection):
    cursor = connection.cursor()
    cursor.execute(" SELECT WindowSize FROM GeneralInfo ")
    windowSize = float(cursor.fetchone()[0])
    return windowSize


def maximum_data_rate(connection):
    memspec = MemSpec(connection)
    memoryType = memspec.getValue("memoryType")
    if (memoryType.find("DDR") != -1):
        width = 64
    else:
        if (memoryType.find("WIDEIO") != -1):
            width = memspec.getValue("width")
    clk = memspec.getValue("clkMhz")
    rate = memspec.getValue("dataRate")
    maxDataRate = float(clk)*float(width)*float(rate)
    return maxDataRate


def getFlexibleRef(connection):
    cursor = connection.cursor()
    cursor.execute(" SELECT  FlexibleRefresh FROM GeneralInfo ")
    result = cursor.fetchone()
    return result[0]


def getMaxRefBurst(connection):
    cursor = connection.cursor()
    cursor.execute(" SELECT  MaxRefBurst FROM GeneralInfo ")
    result = cursor.fetchone()
    return result[0]


def getControllerThread(connection):
    cursor = connection.cursor()
    cursor.execute("SELECT ControllerThread FROM GeneralInfo")
    result = cursor.fetchone()
    return result[0]


def get_phase_occurrences(connection, phase):
    cursor = connection.cursor()
    query = "select count(*) from Phases where PhaseName = :phase"
    cursor.execute(query, {"phase": phase})
    r = cursor.fetchone()
    cnt = r[0]
    if (cnt is None):
        cnt = 0
    return cnt


def get_total_time_in_phase(connection, phase):
    cursor = connection.cursor()
    query = "select sum(PhaseEnd - PhaseBegin) / 1000 from Phases where PhaseName = :phase"
    cursor.execute(query, {"phase": phase})
    time = cursor.fetchone()
    totalTime = time[0]
    if (totalTime is None):
        totalTime = 0.0
    return totalTime
