#!/usr/bin/env python


#
#    Copyright (c) 2015-2017 Nest Labs, Inc.
#    All rights reserved.
#
#    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.
#

#
#    @file
#       Implements WeaveTest class that provides generic Weave testing features.
#

import os
import random
import sys
import time

from happy.Utils import *
from plugins.weave.Weave import Weave

import happy.HappyProcessOutput
import happy.HappyProcessStart
import happy.HappyProcessStop
import happy.HappyProcessStrace
import happy.HappyProcessWait

gready_to_service_events_str = "Weave Node ready to service events"

class WeaveTest(Weave):
    def __init__(self):
        self.ready_to_service_events_str = gready_to_service_events_str
        Weave.__init__(self)
        if "JITTER_DISTRIBUTION_CURVE" in os.environ.keys():
            self.jitter_distribution_curve = int(os.environ["JITTER_DISTRIBUTION_CURVE"])
        else:
            self.jitter_distribution_curve = None


    def start_weave_process(self, node_id, cmd, tag, quiet = None, strace = True, env = {}, sync_on_output = None):
        emsg = "start_weave_process %s at %s node." % (tag, node_id)
        self.logger.debug("[%s] WeaveTest: %s" % (node_id, emsg))

        options = happy.HappyProcessStart.option()
        options["node_id"] = node_id
        options["tag"] = tag
        options["command"] = cmd
        options["strace"] = strace
        options["env"] = env
        options["sync_on_output"] = sync_on_output
        if env:
            options["with_stderr"] = True

        proc = happy.HappyProcessStart.HappyProcessStart(options)
        proc.run()

        time.sleep(0.1)


    def stop_weave_process(self, node_id, tag, quiet = None):
        emsg = "stop_weave_process %s at %s node." % (tag, node_id)
        self.logger.debug("[%s] WeaveTest: %s" % (node_id, emsg))

        options = happy.HappyProcessStop.option()
        options["node_id"] = node_id
        options["tag"] = tag

        stop_server = happy.HappyProcessStop.HappyProcessStop(options)
        stop_server.run()


    def start_simple_weave_server(self, cmd_path, server_addr, node_id, tag, quiet = None, listen = True, strace = True, env = {}, 
                                  sync_on_output = gready_to_service_events_str, use_persistent_storage=True, reset_persistent_storage=True):
        cmd = cmd_path

        if server_addr != None:
            cmd += " --node-addr " + str(server_addr)

        if listen:
            cmd += " --listen"

        persistent_storage_file = self.main_conf['log_directory'] + "/" + self.getStateId() + "_persistent_state." + tag

        if use_persistent_storage:
            cmd += " --persistent-cntr-file " + persistent_storage_file

        if reset_persistent_storage:
            if os.path.isfile(persistent_storage_file):
                self.logger.debug("[%s] WeaveTest: deleting existing persistent storage file: %s" %(node_id, persistent_storage_file))
                os.remove(persistent_storage_file)

        self.logger.debug("[%s] Weave start server on address %s." % (node_id, server_addr))
        emsg = "Weave start server with cmd: %s." % cmd
        self.logger.debug("[%s] Weave: %s" % (node_id, emsg))

        self.start_weave_process(node_id, cmd, tag, quiet, strace, env=env, sync_on_output=sync_on_output)

    def jitter(self, jitter_distribution_curve):
        if isinstance(jitter_distribution_curve, int) and jitter_distribution_curve >= 0:
            fibonacci_numbers = [0, 10]
            if jitter_distribution_curve == 0:
                delayTimeSec = fibonacci_numbers[0]
            elif jitter_distribution_curve == 1:
                delayTimeSec = fibonacci_numbers[1]
            else:
                jitter_distribution_curve -= 2
                for i in xrange(jitter_distribution_curve):
                    fibonacci_numbers.append(fibonacci_numbers[i+1]+fibonacci_numbers[i])
                delayTimeSec = random.choice(fibonacci_numbers)
            self.logger.debug("Test Delay %d seconds" % delayTimeSec)
            time.sleep(delayTimeSec)
        else:
            self.logger.debug("Expect that jitter_distribution_curve is integer and not less than 0 %d" % jitter_distribution_curve)

    def start_simple_weave_client(self, cmd_path, client_addr, server_addr, server_id, node_id, tag, quiet = None, strace = True, env = {}, use_persistent_storage=True, reset_persistent_storage=True):
        cmd = cmd_path

        if client_addr != None:
            cmd += " --node-addr " + str(client_addr)

        if server_addr != None:
            cmd += " --dest-addr " + str(server_addr)

        persistent_storage_file = self.main_conf['log_directory'] + "/" + self.getStateId() + "_persistent_state." + tag

        if use_persistent_storage:
            cmd += " --persistent-cntr-file " + persistent_storage_file

        if reset_persistent_storage:
            if os.path.isfile(persistent_storage_file):
                self.logger.debug("[%s] WeaveTest: deleting existing persistent storage file: %s" %(node_id, persistent_storage_file))
                os.remove(persistent_storage_file)

        if server_id != None:
            cmd += " " + str(server_id)

        if self.jitter_distribution_curve is not None:
            self.jitter(self.jitter_distribution_curve)

        self.logger.debug("[%s] Weave start client on address %s" % (node_id, client_addr))
        emsg = "Weave start client with cmd: %s" % cmd
        self.logger.debug("[%s] Weave: %s" % (node_id, emsg))

        self.start_weave_process(node_id, cmd, tag, quiet, strace, env=env)


    def wait_for_test_to_end(self, node_id, tag, quiet = None, timeout = None):
        emsg = "wait_for_test_to_end for %s at %s node." % (tag, node_id)
        self.logger.debug("[%s] WeaveTest: %s" % (node_id, emsg))

        if timeout == None:
            timeout = self.max_running_time

        options = happy.HappyProcessWait.option()
        options["node_id"] =  node_id
        options["tag"] = tag
        options["timeout"] = timeout

        wait_for_client = happy.HappyProcessWait.HappyProcessWait(options)
        wait_for_client.run()


    def get_test_output(self, node_id, tag, quiet = False):
        emsg = "get_test_output for %s at %s node." % (tag, node_id)
        self.logger.debug("[%s] WeaveTest: %s" % (node_id, emsg))

        options = happy.HappyProcessOutput.option()
        options["node_id"] = node_id
        options["tag"] = tag
        options["quiet"] = quiet

        client_output = happy.HappyProcessOutput.HappyProcessOutput(options)
        ret = client_output.run()

        value = ret.Value()
        data = ret.Data()

        return (value, data)


    def get_test_strace(self, node_id, tag, quiet = None):
        emsg = "get_test_strace for %s at %s node." % (tag, node_id)
        self.logger.debug("[%s] WeaveTest: %s" % (node_id, emsg))

        options = happy.HappyProcessStrace.option()
        options["node_id"] = node_id
        options["tag"] = tag

        client_strace = happy.HappyProcessStrace.HappyProcessStrace(options)
        ret = client_strace.run()

        value = ret.Value()
        data = ret.Data()

        return (value, data)



