# ----------------------------------------------------------------------------
#       Copyright (C) 2013-2014 Huynh Vi Lam  <domovilam@gmail.com>
#
#       This file is part of pimucha.
#
#	This program is free software: you can redistribute it and/or modify
#	it under the terms of the GNU General Public License as published by
#	the Free Software Foundation, either version 3 of the License, or
#	(at your option) any later version.
#	
#	This program is distributed in the hope that it will be useful,
#	but WITHOUT ANY WARRANTY; without even the implied warranty of
#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#	GNU General Public License for more details.
#	
#	You should have received a copy of the GNU General Public License
#	along with this program.  If not, see <http://www.gnu.org/licenses/>.
# ----------------------------------------------------------------------------

import datetime,logging
from piHAparsers.x10libs import (checkhu)
from piHAlibs import (
    dumprows,majdb3,ralldb3,reqdb3,
    newalias,newhu
)
from .aliaslibs import (huorhexid)

logger = logging.getLogger()


def addunit(data):
    """
    item = [typeunit,unitid,protocol,hu,alias]
    typeunit = ['detector','device','remote']
    unitid = addrid (hex form) or hu (houseunit)
    alias = name / label of the unit
    """
    if isinstance(data,list):
        item = data
    else:
        item = data.split()
    if len(item) < 4: return 'Minimum of four parameters needed'
    tu = item[0].lower()
    if tu not in ['detector','device','remote']: return 'Type unit incorrect for this function'
    unitid = huorhexid(item[1])
    protocol = item[2].lower()
    if protocol not in ['x10','x10s','arctech']: return 'Protocol incorrect for this function'
    if not checkhu(item[3]): return 'Syntax error for houseunit code %s' % repr(item[3])
    hu = item[3].upper()
    if len(item) == 4:
        alias = tu + ' ' + hu
    else:
        alias = ' '.join(item[4:])
    alias = alias.replace(' ','_')
    d = datetime.date.strftime(datetime.datetime.today(),"%Y-%m-%d %H:%M:%S").split()
    req = "INSERT INTO unitIds(cdate,ctime,typeunit,iddecoder,unitId,unit,label,enabled) "
    req += " VALUES (?,?,?,?,?,?,?,?);"
    V = [d[0], d[1], tu, protocol, unitid, hu, alias,'True']
    try:
        majdb3(req,V)
        newalias([tu, hu, alias])
    except Exception as e:
        logger.error("Update failed for newids with error : %s",repr(e))
        return "Update failed for newids with error : %s",repr(e)
    return 'Unit %s added successfully' % item[1]


def chgunit(data):
    """
    Affect to an new unitid an existing hu (and alias)
    Remove the new hu (and alias)
    item = [typeunit,unitid,protocol,oldhu,(alias)]
    typeunit = ['detector','device','sensor','remote']
    new unitid (addrid hex form or houseunit) must exist : nhu
    if alias not provided, oldhu must exist (alias exists also)
    if alias provided, add alias and hu
    """
    if isinstance(data,list):
        item = data
    else:
        item = data.split()
    if len(item) < 4: return 'Minimun four parameters needed'
    tu = item[0].lower()
    if tu not in ['detector','device','sensor','remote']: return 'Type unit incorrect for this function'
    oldhu = item[3].upper()
    if not checkhu(oldhu): return 'Syntax error for houseunit code %s' % repr(oldhu)
    protocol = item[2].lower()
    if protocol not in ['x10','x10s','arctech','oregon']: return 'Protocol incorrect for this function'
    #Check new unitId
    req = "SELECT unit FROM unitIds WHERE typeunit = ? AND unitId = ?  ;"
    V = [tu,item[1]]
    r = reqdb3(req,V)
    if r is None:
        return 'UnitId %s must exist in DB' % item[1]
    else:
        nhu = r[0]
    if nhu == oldhu: return 'No change made, unitId and hu represent the same unit'
    #Check oldhu, if alias not provided
    if len(item) == 3:
        req = "SELECT label FROM alias WHERE unit = ?;"
        V = [oldhu,]
        alias = reqdb3(req,V)
        if alias is None: return 'HouseUnit %s (and alias) must exist in DB' % oldhu
        #Remove newhu
        req = "DELETE FROM alias WHERE unit = ?;"
        V = [nhu,]
        majdb3(req,V)
    else:
        #Add alias and hu provided
        alias = ' '.join(item[4:])
        alias = alias.replace(' ','_')
        newalias([tu, oldhu, alias])
    #Change with existing oldhu or hu provided
    req = "UPDATE unitIds SET unit = ? WHERE typeunit = ? AND unitId = ?;"
    V = [oldhu,tu,item[1]]
    majdb3(req,V)
    return 'Changes successful for %s' % data


def lsunit(param,rowids=None):
    param = param.lower()
    if param not in ['all','alias','detector','device','parameter','sensor','remote']: param = 'alias'
    req = "SELECT "
    if param == 'alias':
        req +=  " d.rowId,unit,label,typeunit,enabled FROM alias as d "
        if rowids: req += " WHERE d.rowId IN (" + rowids + ")"
    elif param in ('all','detector','device','sensor','remote'):
        if param == 'all':
            req +=  " 'UNIT',d.typeunit,unitId,iddecoder,d.unit,a.label "
        else:
            req +=  " d.rowId,unitId,iddecoder,d.unit,a.label,cdate,ctime,modelId,d.enabled "
        req +=  " FROM unitIds as d, alias as a WHERE d.unit = a.unit "
        req +=  " AND d.typeunit = a.typeunit "
        if param != 'all':
            req +=  " AND d.typeunit = '" + param.lower() + "' "
        if rowids: req += " AND d.rowId IN (" + rowids + ")"
    elif param == 'parameter':
        req +=  " d.rowId,modaddrId,parameter,unit,updatedmaxt,d.enabled "
        req +=  "FROM parameterIds as d, unitids as a WHERE modaddrid = unitid "
        req +=  " AND a.typeunit = 'sensor' "
        if rowids: req += " AND d.rowId IN (" + rowids + ")"
    rows = ralldb3(req,())
    if not rows : return 'No rows of ' + param + ' in DB'
    return '\n'.join(dumprows(rows))


def enable(data):
    return updunit('True',data)


def disable(data):
    return updunit('False',data)


def updunit(truefalse,data):
    """
    Update field enabled to 'True' or 'False'
    for table parameterIds, unitIds
    item = [truefalse,type,list of rowids]
    truefalse = 'True' or 'False'
    type = ['alias','detector','device','parameter','remote','sensor']
    """
    if isinstance(data,list):
        item = data
    else:
        item = data.split()
    type = ['alias','detector','device','parameter','remote','sensor']
    if item[0] not in type:
        return 'First parameter must be in the list %s' % repr(type)
    if len(item) < 2:
        return 'Syntax error, minimum of one rowId or parameter keyword needed after first argument'
    req = "UPDATE "
    if item[0] == 'alias':
        req += " alias "
    elif item[0] in ('detector','device','remote','sensor'):
        req += " unitids "
    elif item[0] == 'parameter':
        req += " parameterids "
    req += " SET enabled = ? "
    rowids = None
    #Case of parameter keyword
    if (item[0] == 'parameter') and not item[1].isdigit():
        for i in range(1,len(item)):
            item[i] = "'" + item[i] + "'"
        req += " WHERE parameter IN (" + ','.join(item[1:]) + ")"
    else:
        #Check if item is integer for rowId
        for i in range(1,len(item)):
            if not item[i].isdigit(): return 'Syntax error, this parameter %s must be an integer' % repr(item[i])
        rowids = ','.join(item[1:])
        req += " WHERE rowId IN (" + rowids + ")"
    try:
        nb = majdb3(req,(truefalse,))
    except Exception as e:
        return 'Error update :%s' % repr(e)
    if nb > 0:
        if rowids:
            res = lsunit(item[0],rowids)
            return '\tUpdate successful for %s rows \n%s ' % (nb,res)
        else:
            return 'Update successful for %s rows ' % (nb)
    else:
        return 'No update made with %s' % repr (data)
