# -*- coding: utf-8 -*-

# Copyright 2014-2016 Mir Calculate. http://www.calculate-linux.org
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.
import sys
from .output import BaseOutput, BasePositionOutput
from ..text import _uu8
from io import IOBase


class Print():
    """
    Упрощенное получение строки при помощи Output объектов """

    def __init__(self, output=BaseOutput(),
                 position_controller=BasePositionOutput(),
                 printfunc=lambda x: x):
        self.output = output
        self.position_controller = position_controller
        self.buffer = []
        self.printerr = sys.stderr.write
        if isinstance(printfunc, IOBase):
            self.printfunc = printfunc.write
            self.flush = printfunc.flush
        else:
            self.printfunc = printfunc
            self.flush = lambda: None

    @property
    def bold(self):
        self.buffer.append(self.output.setBold())
        return self

    @property
    def underline(self):
        self.buffer.append(self.output.setUnderline())
        return self

    def foreground(self, color):
        self.buffer.append(self.output.setForeground(color))
        return self

    def background(self, color):
        self.buffer.append(self.output.setBackground(color))
        return self

    @property
    def invert(self):
        self.buffer.append(self.output.setInvert())
        return self

    @property
    def halflight(self):
        self.buffer.append(self.output.setHalfbright())
        return self

    def up(self, count):
        self.buffer.append(self.position_controller.moveCursorUp(count))
        return self

    def down(self, count):
        self.buffer.append(self.position_controller.moveCursorDown(count))
        return self

    def right(self, count):
        self.buffer.append(self.position_controller.moveCursorRight(count))
        return self

    def left(self, count):
        self.buffer.append(self.position_controller.moveCursorLeft(count))
        return self

    @property
    def clear_line(self):
        self.buffer.append(self.position_controller.clearLine(whole_line=True))
        return self

    def __call__(self, s, *args, **kwargs):
        err = False
        if 'err' in kwargs:
            err = True
            del kwargs['err']
        if args or kwargs:
            s = s.format(*args, **kwargs)
        self.buffer.append(self.output.outputText(s))
        self.buffer.append(self.output.endText())
        try:
            if err:
                return self.printerr("".join(_uu8(*[x for x in self.buffer if x])))
            else:
                return self.printfunc("".join(_uu8(*[x for x in self.buffer if x])))
        finally:
            self.buffer = []

    def clone(self):
        obj = PrintClone(self.output.clone(),
                         self.position_controller,
                         self.printfunc)
        obj.output.pushState()
        return obj


class PrintClone(Print):
    def __init__(self, output=BaseOutput(),
                 position_controller=BasePositionOutput(),
                 printfunc=lambda x: x):
        super().__init__(output, position_controller, printfunc)

    def __call__(self, s, *args, **kwargs):
        s = s.format(*args, **kwargs)
        self.buffer.append(self.output.outputText(s))
        self.buffer.append(self.output.endText())
        self.output.popState()
        self.output.pushState()
        try:
            return self.printfunc("".join((x for x in self.buffer if x)))
        finally:
            self.buffer = []
