#
# Copyright 2018 the original author or authors.
#
# 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.
#

"""
vOLT-HA Start/Stop module
"""


import os
import subprocess
import testCaseUtils
import logging



class VolthaMngr(object):

    """
    This class implements voltha startup/shutdown callable helper functions
    """

    DEFAULT_ADAPTER = 'ponsim'

    def __init__(self):
        self.dirs = dict()
        self.dirs['root'] = None
        self.dirs['voltha'] = None
        self.dirs['log'] = None
        
    def v_set_log_dirs(self, root_dir, voltha_dir, log_dir):
        testCaseUtils.config_dirs(self, log_dir, root_dir, voltha_dir)

    def start_all_pods(self, adapter=DEFAULT_ADAPTER):
        proc1 = subprocess.Popen([testCaseUtils.get_dir(self, 'root') + '/build.sh', 'start', adapter],
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
        output = proc1.communicate()[0]
        print(output)
        proc1.stdout.close()

    def stop_all_pods(self, adapter=DEFAULT_ADAPTER):
        proc1 = subprocess.Popen([testCaseUtils.get_dir(self, 'root') + '/build.sh', 'stop', adapter],
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
        output = proc1.communicate()[0]
        print(output)
        proc1.stdout.close()
        
    def reset_kube_adm(self, adapter=DEFAULT_ADAPTER):
        proc1 = subprocess.Popen([testCaseUtils.get_dir(self, 'root') + '/build.sh', 'clear', adapter],
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
        output = proc1.communicate()[0]
        print(output)
        proc1.stdout.close()

    """
    Because we are not deploying SEBA with XOS and NEM, and that a standalone Voltha
    deployment is not common, in order to get flows to work, we need to alter Onos 
    NetCfg in two fashion.
    One is to add to device list and the other is to add the missing Sadis section
    """        
    def alter_onos_net_cfg(self):
        logging.info('Altering the Onos NetCfg to suit Voltha\'s needs')
        logging.debug('curl --user karaf:karaf -X POST -H "Content-Type: application/json" '
                      'http://localhost:30120/onos/v1/network/configuration/devices/ -d @%s/tests/atests/build/devices_json'
                      % testCaseUtils.get_dir(self, 'voltha'))
        os.system('curl --user karaf:karaf -X POST -H "Content-Type: application/json" '
                  'http://localhost:30120/onos/v1/network/configuration/devices/ -d @%s/tests/atests/build/devices_json'
                  % testCaseUtils.get_dir(self, 'voltha'))
        logging.debug('curl --user karaf:karaf -X POST -H "Content-Type: application/json" '
                      'http://localhost:30120/onos/v1/network/configuration/apps/ -d @%s/tests/atests/build/sadis_json'
                      % testCaseUtils.get_dir(self, 'voltha'))
        os.system('curl --user karaf:karaf -X POST -H "Content-Type: application/json" '
                  'http://localhost:30120/onos/v1/network/configuration/apps/ -d @%s/tests/atests/build/sadis_json'
                  % testCaseUtils.get_dir(self, 'voltha'))

    def collect_pod_logs(self):
        logging.info('Collect logs from all Pods')
        allRunningPods = get_all_running_pods()
        for nsName in allRunningPods:
            Namespace = nsName.get('NS')
            podName = nsName.get('Name')
            if 'onos' in podName:
                os.system('/usr/bin/kubectl logs -n %s -f %s onos > %s/%s.log 2>&1 &' %
                          (Namespace, podName, testCaseUtils.get_dir(self, 'log'), podName))
            elif 'calico-node' in podName:
                    os.system('/usr/bin/kubectl logs -n %s -f %s calico-node > %s/%s.log 2>&1 &' %
                              (Namespace, podName, testCaseUtils.get_dir(self, 'log'), podName))
            else:
                os.system('/usr/bin/kubectl logs -n %s -f %s > %s/%s.log 2>&1 &' %
                          (Namespace, podName, testCaseUtils.get_dir(self, 'log'), podName))

        
def get_all_running_pods():
    allRunningPods = []
    proc1 = subprocess.Popen(['/usr/bin/kubectl', 'get', 'pods', '--all-namespaces'],
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
    proc2 = subprocess.Popen(['grep', '-v', 'NAMESPACE'], stdin=proc1.stdout,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
    proc1.stdout.close()
    out, err = proc2.communicate()
    print(out)
    if out:
        for line in out.split('\n'):
            items = line.split()
            if len(items) > 2:
                nsName = dict()
                nsName['NS'] = items[0]
                nsName['Name'] = items[1]
                allRunningPods.append(nsName)
    return allRunningPods


def voltha_initialize(root_dir, voltha_dir, log_dir, adapter):
    voltha = VolthaMngr()
    voltha.v_set_log_dirs(root_dir, voltha_dir, log_dir)
    voltha.stop_all_pods(adapter)
    voltha.reset_kube_adm(adapter)
    voltha.start_all_pods(adapter)
    voltha.alter_onos_net_cfg()
    voltha.collect_pod_logs()
