#! /usr/bin/python
'''
Copyright 2016 Intel Corporation

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.
'''

from cmd import Cmd
import os
import subprocess
import re
import sys
from optparse import OptionParser

try:
        import readline
except ImportError:
        readline = None

persishist = os.path.expanduser('~/.vpphistory')
persishist_size = 1000
if not persishist:
        os.mknod(persishist, stat.S_IFREG)

class Vppctl(Cmd):

        def __init__(self,api_prefix=None):
                Cmd.__init__(self)
                self.api_prefix = api_prefix

        def historyWrite(self):
                if readline:
                        readline.set_history_length(persishist_size)
                        readline.write_history_file(persishist)

        def runVat(self, line):
                input_prefix = "exec "
                input_command = input_prefix + line
                line_remove = '^load_one_plugin:'
                s = '\n'
                if ( self.api_prefix is None):
                        command = ['vpp_api_test']
                else:
                        command = ['vpp_api_test',"chroot prefix %s " % self.api_prefix]

                if os.geteuid() != 0:
                    command = ['sudo'] + command

                vpp_process = subprocess.Popen(command,
                        stderr=subprocess.PIPE,
                        stdin=subprocess.PIPE,
                        stdout=subprocess.PIPE)
                stdout_value = vpp_process.communicate(input_command)[0]

                buffer_stdout = stdout_value.splitlines()

                buffer_stdout[:]  = [b for b in buffer_stdout
                        if line_remove not in b]

                for i, num in enumerate(buffer_stdout):
                        buffer_stdout[i] = num.replace('vat# ','')

                stdout_value = s.join(buffer_stdout)
                print stdout_value

        def do_help(self, line):
                self.runVat("help")

        def default(self, line):
                self.runVat(line)

        def do_exit(self, line):
                self.historyWrite()
                raise SystemExit

        def emptyline(self):
                pass

        def do_EOF(self,line):
                self.historyWrite()
                sys.stdout.write('\n')
                raise SystemExit

        def preloop(self):
                if readline and os.path.exists(persishist):
                        readline.read_history_file(persishist)

        def postcmd(self, stop, line):
                self.historyWrite()

if __name__ == '__main__':
        parser = OptionParser()
        parser.add_option("-p","--prefix",action="store",type="string",dest="prefix")
        (options,command_args) = parser.parse_args(sys.argv)

        if not len(command_args) > 1:
                prompt = Vppctl(options.prefix)
                red_set = '\033[31m'
                norm_set = '\033[0m'
                if sys.stdout.isatty():
                        if(options.prefix is None):
                                prompt.prompt = 'vpp# '
                        else:
                                prompt.prompt = '%s# ' % options.prefix
                        try:
                                prompt.cmdloop(red_set + "    _______    _       " + norm_set + " _   _____  ___ \n" +
                                        red_set + " __/ __/ _ \  (_)__   " + norm_set + " | | / / _ \/ _ \\\n" +
                                        red_set + " _/ _// // / / / _ \\" + norm_set + "   | |/ / ___/ ___/\n" +
                                        red_set + " /_/ /____(_)_/\___/   " + norm_set + "|___/_/  /_/   \n")
                        except KeyboardInterrupt:
                                sys.stdout.write('\n')
                else:
                        try:
                                prompt.cmdloop()
                        except KeyboardInterrupt:
                                sys.stdout.write('\n')
        else:
                del command_args[0]
                stdout_value = " ".join(command_args)
                VatAddress = Vppctl(options.prefix)
                VatAddress.runVat(stdout_value)



