#
# BitBake Curses UI Implementation
#
# Implements an ncurses frontend for the BitBake utility.
#
# Copyright (C) 2006 Michael 'Mickey' Lauer
# Copyright (C) 2006-2007 Richard Purdie
#
# SPDX-License-Identifier: GPL-2.0-only
#

"""
    We have the following windows:

        1.) Main Window: Shows what we are ultimately building and how far we are. Includes status bar
        2.) Thread Activity Window: Shows one status line for every concurrent bitbake thread.
        3.) Command Line Window: Contains an interactive command line where you can interact w/ Bitbake.

    Basic window layout is like that:

        |---------------------------------------------------------|
        | <Main Window>               | <Thread Activity Window>  |
        |                             | 0: foo do_compile complete|
        | Building Gtk+-2.6.10        | 1: bar do_patch complete  |
        | Status: 60%                 | ...                       |
        |                             | ...                       |
        |                             | ...                       |
        |---------------------------------------------------------|
        |<Command Line Window>                                    |
        |>>> which virtual/kernel                                 |
        |openzaurus-kernel                                        |
        |>>> _                                                    |
        |---------------------------------------------------------|

"""



import logging
import os, sys, itertools, time, subprocess

try:
    import curses
except ImportError:
    sys.exit("FATAL: The ncurses ui could not load the required curses python module.")

import bb
import xmlrpc.client
from bb import ui
from bb.ui import uihelper

parsespin = itertools.cycle( r'|/-\\' )

X = 0
Y = 1
WIDTH = 2
HEIGHT = 3

MAXSTATUSLENGTH = 32

class NCursesUI:
    """
    NCurses UI Class
    """
    class Window:
        """Base Window Class"""
        def __init__( self, x, y, width, height, fg=curses.COLOR_BLACK, bg=curses.COLOR_WHITE ):
            self.win = curses.newwin( height, width, y, x )
            self.dimensions = ( x, y, width, height )
            """
            if curses.has_colors():
                color = 1
                curses.init_pair( color, fg, bg )
                self.win.bkgdset( ord(' '), curses.color_pair(color) )
            else:
                self.win.bkgdset( ord(' '), curses.A_BOLD )
            """
            self.erase()
            self.setScrolling()
            self.win.noutrefresh()

        def erase( self ):
            self.win.erase()

        def setScrolling( self, b = True ):
            self.win.scrollok( b )
            self.win.idlok( b )

        def setBoxed( self ):
            self.boxed = True
            self.win.box()
            self.win.noutrefresh()

        def setText( self, x, y, text, *args ):
            self.win.addstr( y, x, text, *args )
            self.win.noutrefresh()

        def appendText( self, text, *args ):
            self.win.addstr( text, *args )
            self.win.noutrefresh()

        def drawHline( self, y ):
            self.win.hline( y, 0, curses.ACS_HLINE, self.dimensions[WIDTH] )
            self.win.noutrefresh()

    class DecoratedWindow( Window ):
        """Base class for windows with a box and a title bar"""
        def __init__( self, title, x, y, width, height, fg=curses.COLOR_BLACK, bg=curses.COLOR_WHITE ):
            NCursesUI.Window.__init__( self, x+1, y+3, width-2, height-4, fg, bg )
            self.decoration = NCursesUI.Window( x, y, width, height, fg, bg )
            self.decoration.setBoxed()
            self.decoration.win.hline( 2, 1, curses.ACS_HLINE, width-2 )
            self.setTitle( title )

        def setTitle( self, title ):
            self.decoration.setText( 1, 1, title.center( self.dimensions[WIDTH]-2 ), curses.A_BOLD )

    #-------------------------------------------------------------------------#
#    class TitleWindow( Window ):
    #-------------------------------------------------------------------------#
#        """Title Window"""
#        def __init__( self, x, y, width, height ):
#            NCursesUI.Window.__init__( self, x, y, width, height )
#            version = bb.__version__
#            title = "BitBake %s" % version
#            credit = "(C) 2003-2007 Team BitBake"
#            #self.win.hline( 2, 1, curses.ACS_HLINE, width-2 )
#            self.win.border()
#            self.setText( 1, 1, title.center( self.dimensions[WIDTH]-2 ), curses.A_BOLD )
#            self.setText( 1, 2, credit.center( self.dimensions[WIDTH]-2 ), curses.A_BOLD )

    #-------------------------------------------------------------------------#
    class ThreadActivityWindow( DecoratedWindow ):
    #-------------------------------------------------------------------------#
        """Thread Activity Window"""
        def __init__( self, x, y, width, height ):
            NCursesUI.DecoratedWindow.__init__( self, "Thread Activity", x, y, width, height )

        def setStatus( self, thread, text ):
            line = "%02d: %s" % ( thread, text )
            width = self.dimensions[WIDTH]
            if ( len(line) > width ):
                line = line[:width-3] + "..."
            else:
                line = line.ljust( width )
            self.setText( 0, thread, line )

    #-------------------------------------------------------------------------#
    class MainWindow( DecoratedWindow ):
    #-------------------------------------------------------------------------#
        """Main Window"""
        def __init__( self, x, y, width, height ):
            self.StatusPosition = width - MAXSTATUSLENGTH
            NCursesUI.DecoratedWindow.__init__( self, None, x, y, width, height )
            curses.nl()

        def setTitle( self, title ):
            title = "BitBake %s" % bb.__version__
            self.decoration.setText( 2, 1, title, curses.A_BOLD )
            self.decoration.setText( self.StatusPosition - 8, 1, "Status:", curses.A_BOLD )

        def setStatus(self, status):
            while len(status) < MAXSTATUSLENGTH:
                status = status + " "
            self.decoration.setText( self.StatusPosition, 1, status, curses.A_BOLD )


    #-------------------------------------------------------------------------#
    class ShellOutputWindow( DecoratedWindow ):
    #-------------------------------------------------------------------------#
        """Interactive Command Line Output"""
        def __init__( self, x, y, width, height ):
            NCursesUI.DecoratedWindow.__init__( self, "Command Line Window", x, y, width, height )

    #-------------------------------------------------------------------------#
    class ShellInputWindow( Window ):
    #-------------------------------------------------------------------------#
        """Interactive Command Line Input"""
        def __init__( self, x, y, width, height ):
            NCursesUI.Window.__init__( self, x, y, width, height )

# put that to the top again from curses.textpad import Textbox
#            self.textbox = Textbox( self.win )
#            t = threading.Thread()
#            t.run = self.textbox.edit
#            t.start()

    #-------------------------------------------------------------------------#
    def main(self, stdscr, server, eventHandler, params):
    #-------------------------------------------------------------------------#
        height, width = stdscr.getmaxyx()

        # for now split it like that:
        # MAIN_y + THREAD_y = 2/3 screen at the top
        # MAIN_x = 2/3 left, THREAD_y = 1/3 right
        # CLI_y = 1/3 of screen at the bottom
        # CLI_x = full

        main_left = 0
        main_top = 0
        main_height = ( height // 3 * 2 )
        main_width = ( width // 3 ) * 2
        clo_left = main_left
        clo_top = main_top + main_height
        clo_height = height - main_height - main_top - 1
        clo_width = width
        cli_left = main_left
        cli_top = clo_top + clo_height
        cli_height = 1
        cli_width = width
        thread_left = main_left + main_width
        thread_top = main_top
        thread_height = main_height
        thread_width = width - main_width

        #tw = self.TitleWindow( 0, 0, width, main_top )
        mw = self.MainWindow( main_left, main_top, main_width, main_height )
        taw = self.ThreadActivityWindow( thread_left, thread_top, thread_width, thread_height )
        clo = self.ShellOutputWindow( clo_left, clo_top, clo_width, clo_height )
        cli = self.ShellInputWindow( cli_left, cli_top, cli_width, cli_height )
        cli.setText( 0, 0, "BB>" )

        mw.setStatus("Idle")

        helper = uihelper.BBUIHelper()
        shutdown = 0

        try:
            params.updateFromServer(server)
            cmdline = params.parseActions()
            if not cmdline:
                print("Nothing to do.  Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
                return 1
            if 'msg' in cmdline and cmdline['msg']:
                logger.error(cmdline['msg'])
                return 1
            cmdline = cmdline['action']
            ret, error = server.runCommand(cmdline)
            if error:
                print("Error running command '%s': %s" % (cmdline, error))
                return
            elif ret != True:
                print("Couldn't get default commandlind! %s" % ret)
                return
        except xmlrpc.client.Fault as x:
            print("XMLRPC Fault getting commandline:\n %s" % x)
            return

        exitflag = False
        while not exitflag:
            try:
                event = eventHandler.waitEvent(0.25)
                if not event:
                    continue

                helper.eventHandler(event)
                if isinstance(event, bb.build.TaskBase):
                    mw.appendText("NOTE: %s\n" % event._message)
                if isinstance(event, logging.LogRecord):
                    mw.appendText(logging.getLevelName(event.levelno) + ': ' + event.getMessage() + '\n')

                if isinstance(event, bb.event.CacheLoadStarted):
                    self.parse_total = event.total
                if isinstance(event, bb.event.CacheLoadProgress):
                    x = event.current
                    y = self.parse_total
                    mw.setStatus("Loading Cache:   %s [%2d %%]" % ( next(parsespin), x*100/y ) )
                if isinstance(event, bb.event.CacheLoadCompleted):
                    mw.setStatus("Idle")
                    mw.appendText("Loaded %d entries from dependency cache.\n"
                                % ( event.num_entries))

                if isinstance(event, bb.event.ParseStarted):
                    self.parse_total = event.total
                if isinstance(event, bb.event.ParseProgress):
                    x = event.current
                    y = self.parse_total
                    mw.setStatus("Parsing Recipes: %s [%2d %%]" % ( next(parsespin), x*100/y ) )
                if isinstance(event, bb.event.ParseCompleted):
                    mw.setStatus("Idle")
                    mw.appendText("Parsing finished. %d cached, %d parsed, %d skipped, %d masked.\n"
                                % ( event.cached, event.parsed, event.skipped, event.masked ))

#                if isinstance(event, bb.build.TaskFailed):
#                    if event.logfile:
#                        if data.getVar("BBINCLUDELOGS", d):
#                            bb.error("log data follows (%s)" % logfile)
#                            number_of_lines = data.getVar("BBINCLUDELOGS_LINES", d)
#                            if number_of_lines:
#                                subprocess.check_call('tail -n%s %s' % (number_of_lines, logfile), shell=True)
#                            else:
#                                f = open(logfile, "r")
#                                while True:
#                                    l = f.readline()
#                                    if l == '':
#                                        break
#                                    l = l.rstrip()
#                                    print '| %s' % l
#                                f.close()
#                        else:
#                            bb.error("see log in %s" % logfile)

                if isinstance(event, bb.command.CommandCompleted):
                    # stop so the user can see the result of the build, but
                    # also allow them to now exit with a single ^C
                    shutdown = 2
                if isinstance(event, bb.command.CommandFailed):
                    mw.appendText(str(event))
                    time.sleep(2)
                    exitflag = True
                if isinstance(event, bb.command.CommandExit):
                    exitflag = True
                if isinstance(event, bb.cooker.CookerExit):
                    exitflag = True

                if isinstance(event, bb.event.LogExecTTY):
                    mw.appendText('WARN: ' + event.msg + '\n')
                if helper.needUpdate:
                    activetasks, failedtasks = helper.getTasks()
                    taw.erase()
                    taw.setText(0, 0, "")
                    if activetasks:
                        taw.appendText("Active Tasks:\n")
                        for task in activetasks.values():
                            taw.appendText(task["title"] + '\n')
                    if failedtasks:
                        taw.appendText("Failed Tasks:\n")
                        for task in failedtasks:
                            taw.appendText(task["title"] + '\n')

                curses.doupdate()
            except EnvironmentError as ioerror:
                # ignore interrupted io
                if ioerror.args[0] == 4:
                    pass

            except KeyboardInterrupt:
                if shutdown == 2:
                    mw.appendText("Third Keyboard Interrupt, exit.\n")
                    exitflag = True
                if shutdown == 1:
                    mw.appendText("Second Keyboard Interrupt, stopping...\n")
                    _, error = server.runCommand(["stateForceShutdown"])
                    if error:
                        print("Unable to cleanly stop: %s" % error)
                if shutdown == 0:
                    mw.appendText("Keyboard Interrupt, closing down...\n")
                    _, error = server.runCommand(["stateShutdown"])
                    if error:
                        print("Unable to cleanly shutdown: %s" % error)
                shutdown = shutdown + 1
                pass

def main(server, eventHandler, params):
    if not os.isatty(sys.stdout.fileno()):
        print("FATAL: Unable to run 'ncurses' UI without a TTY.")
        return
    ui = NCursesUI()
    try:
        curses.wrapper(ui.main, server, eventHandler, params)
    except:
        import traceback
        traceback.print_exc()
