#!/usr/bin/python
# -*- coding: utf-8 -*-
# pylint: disable=I0011,W0231

import time
import smbus  # pylint: disable=I0011,F0401
from charlcd.drivers.base import BaseDriver


class I2C(BaseDriver):
    """I2C LCD driver"""
    def __init__(self, address, port):
        """
        Set address port, pins
        Args:
            address: hex i2c address
            port: bus number
        """
        self.address = address
        self.port = port
        self.mode = 8
        self.pins = {
            'RS': 0,
            'E': 2,
            'E2': None,
            'DB4': 4,
            'DB5': 5,
            'DB6': 6,
            'DB7': 7,
            'RW': 1,
            'BT': 3,
        }
        self.bus = smbus.SMBus(port)
        self.char_buffer = None
        self.initialized = False

    def init(self):
        """recalculate pins to values"""
        if self.initialized:
            return
        pins = {}
        for k in self.pins:
            if self.pins[k] is not None:
                pins[k] = int(pow(2, self.pins[k]))
        self.pins = pins
        self.initialized = True

    def cmd(self, char, enable=0):
        """
        Send command to lcd
        Args:
            char: hex command to write
        """

        if self.mode == 8:
            self.prepare_send((char << 4) & 0xF0, enable)
        else:
            self.prepare_send(char & 0xF0, enable)
            self.prepare_send((char << 4) & 0xF0, enable)

    def shutdown(self):
        """shutdown routine"""
        pass

    def prepare_send(self, char, enable=0):
        """
        Prepares data for send and call send
            char: char to write
            enable: line to use
        """
        self.char_buffer = char | self.pins['BT']
        self.send(enable)

    def send(self, enable=0):
        """
        Send enable signal
        Args:
            enable: line to use
        """
        if enable == 0:
            pin = self.pins['E']
        elif enable == 1:
            pin = self.pins['E2']

        if pin is None:
            raise IndexError("Wrong enable index")
        self.write(self.char_buffer | pin)
        time.sleep(0.005)
        self.write(self.char_buffer & (0xFF - pin))

    def write(self, char, enable=0):
        """
        Write data to bus
        Args:
            byte: hex to write to i2c bus
        """
        self.bus.write_byte(self.address, char)

    def char(self, char, enable=0):
        """
        Send char
        Args:
            char: char to swrite
            enable: enable line
        """
        char = ord(char)
        if self.mode == 8:
            self.prepare_send(self.pins['RS'] | (char & 0x0F), enable)
        else:
            self.prepare_send((char & 0xF0) | self.pins['RS'], enable)
            self.prepare_send(((char << 4) & 0xF0) | self.pins['RS'], enable)

    def set_mode(self, mode):
        """
        Set working mode (4/8-bit)
        Args:
            mode: mode to set
        """
        self.mode = mode
