import iso8601
from typing import (
    Dict,
    List,
)

from devicemanager.model import (
    DeviceStatus,
    DeviceStatusHistory,
)
from devicemanager.repository import DeviceManagerRepository
from externals.persist import ConnectionWrapper


class SqliteDeviceManagerRepository(DeviceManagerRepository):

    def __init__(
        self,
        conn,   # type: ConnectionWrapper
    ):
        self.conn = conn

    def get_disabled_devices(
        self,   # type: SqliteDeviceManagerRepository
    ):
        # type: (...) -> Dict[str, DeviceStatus]

        query = """
            SELECT DeviceName 
            FROM DisabledDevices
        """
        cursor = self.conn.select(sql=query)

        ret = {}
        for row in cursor:
            device = DeviceStatus(
                device_name=row.get_entry("DeviceName").decode("utf-8"),
                enabled=False,
            )
            ret[device.device_name] = device
        return ret

    def get_devices_with_last_history(
        self,           # type: SqliteDeviceManagerRepository
        device_names,   # type: List[str]
    ):
        # type: (...) -> List[DeviceStatus]

        query = """
            SELECT 
                dh.DeviceName, 
                dh.Operator, 
                dh.Timestamp, 
                dd.DeviceName IS NOT NULL AS Enabled
            FROM 
            (
                SELECT 
                    DeviceName, 
                    Operator, 
                    MAX(Timestamp ) AS Timestamp
                FROM DeviceStatusHistory 
                WHERE DeviceName IN ({})
                GROUP BY DeviceName
            ) dh 
            LEFT OUTER JOIN DisabledDevices dd on dh.DeviceName = dd.DeviceName
        """.format("'{}'".format("','".join(device_names)))

        cursor = self.conn.select(sql=query)

        ret = []
        for row in cursor:
            enabled = int(row.get_entry("Enabled")) == 0
            device = DeviceStatus(
                device_name=row.get_entry("DeviceName").decode("utf-8"),
                enabled=enabled,
                history=[
                    DeviceStatusHistory(
                        enabled=enabled,
                        operator=row.get_entry("Operator").decode("utf-8"),
                        timestamp=iso8601.parse_date(row.get_entry("Timestamp")),
                    )
                ]
            )
            ret.append(device)
        return ret

    def create_device_status(
        self,           # type: SqliteDeviceManagerRepository
        device_name,    # type: str
    ):
        # type: (...) -> None

        query = """
            INSERT INTO DisabledDevices (DeviceName) 
            VALUES ('{}')
        """.format(device_name)
        self.conn.query(sql=query)

    def delete_device_status(
        self,           # type: SqliteDeviceManagerRepository
        device_name,    # type: str
    ):
        # type: (...) -> None

        query = """
            DELETE FROM DisabledDevices 
            WHERE DeviceName = '{}'
        """.format(device_name)
        self.conn.query(sql=query)

    def create_device_status_history(
        self,                   # type: SqliteDeviceManagerRepository
        device_name,            # type: str
        device_status_history,  # type: DeviceStatusHistory
    ):
        # type: (...) -> None

        query = """
            INSERT INTO DeviceStatusHistory (
              DeviceName, 
              Enabled,
              Operator,
              Timestamp
            ) VALUES (
             '{}', 
             '{}',
             '{}',
             '{}'
             )
        """.format(
            device_name,
            str(device_status_history.enabled).lower(),
            device_status_history.operator.encode("utf-8"),
            device_status_history.timestamp.isoformat(),
        )

        self.conn.query(sql=query)
