#!/usr/bin/python
import os
import sys
import curses
import traceback
import argparse

banner="\
#########  #########    #########      #######    #########   \n \
#########  ##########   ##########    #########   ##########  \n \
###        ###     ###  ###     ###  ####   ####  ###     ### \n \
###        ###     ###  ###     ###  ###     ###  ###     ### \n \
###        ###     ###  ###     ###  ###     ###  ###     ### \n \
########   ##########   ##########   ###     ###  ##########  \n \
########   #########    #########    ###     ###  #########   \n \
###        ###   ###    ###   ###    ###     ###  ###   ###   \n \
###        ###    ###   ###    ###   ###     ###  ###    ###  \n \
###        ###     ###  ###     ###  ####   ####  ###     ### \n \
#########  ###     ###  ###     ###   #########   ###     ### \n \
#########  ###     ###  ###     ###    #######    ###     ### \n \
"

class ErrorDialog():
    def __init__(self, msg=None, banner=banner):
        self.msg = None
        self.msg_rows = 0
        self.msg_cols = 0
        self.banner = None
        self.banner_rows = 0
        self.banner_cols = 0
        self.max_rows = 0
        self.max_cols = 0
        self.h_padding = 10
        self.v_padding = 2

        try:
            self.screen = curses.initscr()
            curses.start_color()
            curses.noecho()
            curses.init_pair(9, curses.COLOR_BLACK, curses.COLOR_BLUE)
            curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_RED)

            self.screen.bkgd(curses.color_pair(9))
            self.screen.refresh()
            self.max_rows, self.max_cols = self.screen.getmaxyx()
        except:
            curses.endwin()
            print sys.stderr, traceback.format_exc()

        if msg != None:
            self.SetText(msg)

        if banner != None:
            self.SetBanner(banner)

    def CreateBox(self):
        box_width = max(self.banner_cols + self.h_padding * 2,
                        self.msg_cols + self.h_padding * 2)

        box_height = self.banner_rows + self.msg_rows + 1 + self.v_padding * 2

        start_x = (self.max_cols - box_width) / 2
        start_y = (self.max_rows - box_height) / 2

        try:
            self.box = curses.newwin(box_height, box_width, start_y, start_x)
            self.box.bkgd(curses.color_pair(1))
            self.box.box()

            i = self.v_padding
            for line in self.banner.split('\n'):
                self.box.addstr(i, self.h_padding, line.strip())
                i += 1
            # add gap
            self.box.addstr(i, self.h_padding, '')
            i+=1

            for line in self.msg.split('\n'):
                self.box.addstr(i, self.h_padding, line.strip())
                i += 1

            reboot_msg = "  Press [ENTER] too reboot system  "
            self.box.addstr(box_height - 1, (box_width - len(reboot_msg))/2, reboot_msg)
            self.box.refresh()

        except:
            curses.endwin()

    def SetText(self, txt):
        for line in txt.strip().split('\n'):
            self.msg_rows += 1
            if len(line) > self.msg_cols:
                self.msg_cols = len(line)
        self.msg = txt.strip()

    def SetBanner(self, banner):
        for line in banner.strip().split('\n'):
            self.banner_rows += 1
            if len(line) > self.banner_rows:
                self.banner_cols = len(line)
        self.banner = banner.strip()

    def Post(self):
        self.CreateBox()
        while True:
            c = self.screen.getch()
            if c in (curses.KEY_ENTER, 10):
                break
            self.screen.refresh()
            self.box.refresh()
        curses.endwin()

    @staticmethod
    def Close():
        curses.endwin()


if __name__ == "__main__":
    prog = os.path.basename(__file__)
    parser = argparse.ArgumentParser(description='Display an error dialog on the terminal')
    parser.add_argument('text', help='Error mesage to be displayed')

    args = parser.parse_args()
    try:
        err = ErrorDialog(args.text.replace("\\n", "\n"))
        err.Post()
    except KeyboardInterrupt:
        ErrorDialog.Close()
