#!/usr/bin/env python
#coding=utf8

'''
CloudControl CLI Printer module
'''

import sys
import os
import getpass

import cccli
from cccli.exception import *

color = {
    # regular
    "red": "\033[0;31m",
    "green": "\033[0;32m",
    "yellow": "\033[0;33m",
    "blue": "\033[0;34m",
    "purple": "\033[0;35m",
    "cyan": "\033[0;36m",
    "white": "\033[0;37m",
    # lighted
    "lred": "\033[1;31m",
    "lgreen": "\033[1;32m",
    "lyellow": "\033[1;33m",
    "lblue": "\033[1;34m",
    "lpurple": "\033[1;35m",
    "lcyan": "\033[1;36m",
    "lwhite": "\033[1;37m",
    # underline
    "ured": "\033[4;31m",
    "ugreen": "\033[4;32m",
    "uyellow": "\033[4;33m",
    "ublue": "\033[4;34m",
    "upurple": "\033[4;35m",
    "ucyan": "\033[4;36m",
    # others
    "light": "\033[1m",
    "reset": "\033[m",
    }


class Printer(object):
    '''Print relative class'''
    def __init__(self, interactive=False, forceyes=False, historyfile=None, historysize=None):
        self.readline = None
        self.history = History()
        self.historyfile = historyfile
        self.historysize = historysize
        self.forceyes = forceyes
        if interactive:
            self.setinteractive()

    def isinteractive(self):
        '''Return if printer is in interactive mode'''
        return self.readline is not None

    def setinteractive(self):
        if self.readline is not None:
            return
        import readline
        self.readline = readline
        if self.history is None:
            self.history = History(self.readline)
        else:
            self.history.readline = readline
        self.history.load(self.historyfile)
        self.history.maxsize(self.historysize)

    def out(self, message="", fd=sys.stdout, nl=os.linesep, flush=True):
        '''Print a message in fd ended by nl'''
        fd.write("%s%s"%(message, nl))
        if flush:
            fd.flush()

    def err(self, message, fd=sys.stderr, nl=os.linesep):
        self.out(message, fd, nl)

    def fatal(self, message, quit=True, fd=sys.stderr, nl=os.linesep):
        self.out("%sFatal%s: %s%s"%(color["lred"],color["red"],message, color["reset"]),
            fd,
            nl)
        if quit:
            os.kill(0, 15)

    def error(self, message, fd=sys.stderr, nl=os.linesep):
        self.out("%sError%s: %s%s"%(color["lred"],color["red"],message,color["reset"]),
                 fd,
                 nl)

    def warn(self, message, fd=sys.stderr, nl=os.linesep):
        self.out("%sWarning%s: %s%s"%(color["lyellow"],color["yellow"],message,color["reset"]),
                 fd,
                 nl)

    def debug(self, message, fd=sys.stderr, nl=os.linesep):
        if cccli.debug:
            self.out(message, fd, nl)

    def getline(self, prompt, history=True):
        try:
            s = raw_input(prompt)
        except EOFError:
            raise
        except KeyboardInterrupt:
            raise
        except:
            raise cliError
        if not history and s:
            self.history.removelast()
        return s

    def getpass(self, prompt):
        '''Ask for a password. No echo. Not in history'''
        if self.readline is None:
            raise cliError("Unable to ask a password in non-interactive mode")
        return getpass.getpass(prompt)

    def ask(self, prompt, goodans=None):
        '''Used to ask a question. Default answer not saved to history'''
        if self.forceyes and goodans is not None:
            return goodans
        if self.readline is None:
            raise cliError("Unable to ask question in non-interactive mode")
        return self.getline(prompt, history=False)


class History(object):
    '''History class'''
    def __init__(self):
        self.readline = None

    def __nonzero__(self):
        return self.readline is not None

    def __getattribute__(self, name):
        r = object.__getattribute__(self, "readline")
        if name == "readline":
            return r
        if r is None:
            return lambda *a,**k: None
        return object.__getattribute__(self, name)

    def __iter__(self):
        for i in range(1, len(self)):
            yield self.readline.get_history_item(i)

    def __len__(self):
        if self.readline is None:
            return 0
        return self.readline.get_current_history_length()

    def load(self, path):
        '''Load history from a file'''
        try:
            self.readline.read_history_file(path)
        except IOError:
            pass

    def save(self, path):
        '''Save history into path'''
        try:
            self.readline.write_history_file(path)
        except IOError:
            pass

    def maxsize(self, size=None):
        '''Set or return max history size'''
        if size is not None:
            self.readline.set_history_length(size)
        return self.readline.get_history_length()

    def removelast(self):
        '''Remove last history line'''
        self.readline.remove_history_item(self.readline.get_current_history_length() - 1)

    def clear(self):
        '''Clear history'''
        self.readline.clear_history()