import os
import sys
import time
import json
import glob
import signal
import os.path
import argparse

from .sensors.utils import SensorInfo
from .daemonize import Daemonize
from .discover import all_sensors
from .protocol import create_protocol


# load all sensors
from . import sensors
sensors_dir = os.path.dirname(sensors.__file__)
for fname in glob.glob(os.path.join(sensors_dir, "*.py")):
    mod_name = os.path.basename(fname[:-3])
    __import__("sensors.sensors." + mod_name)


def get_values(required_sensors):
    result = {}
    for sensor_name, params in required_sensors:
        if sensor_name in all_sensors:
            result.update(all_sensors[sensor_name](**params))
        else:
            msg = "Sensor {0!r} isn't available".format(sensor_name)
            raise ValueError(msg)
    return time.time(), result


def parse_args(args):
    parser = argparse.ArgumentParser()
    parser.add_argument('-d', '--daemon',
                        choices=('start', 'stop', 'status'),
                        default=None)

    parser.add_argument('-u', '--url', default='stdout://')
    parser.add_argument('-t', '--timeout', type=float, default=1)
    parser.add_argument('-l', '--list-sensors', action='store_true')
    parser.add_argument('sensors_config', type=argparse.FileType('r'),
                        default=None, nargs='?')
    return parser.parse_args(args[1:])


def daemon_main(required_sensors, opts):
    try:
        source_id = str(required_sensors.pop('source_id'))
    except KeyError:
        source_id = None

    sender = create_protocol(opts.url)
    prev = {}

    while True:
        gtime, data = get_values(required_sensors.items())
        curr = {'time': SensorInfo(gtime, True)}
        for name, val in data.items():
            if val.is_accumulated:
                if name in prev:
                    curr[name] = SensorInfo(val.value - prev[name], True)
                prev[name] = val.value
            else:
                curr[name] = SensorInfo(val.value, False)

        if source_id is not None:
            curr['source_id'] = source_id

        sender.send(curr)

        time.sleep(opts.timeout)


def pid_running(pid):
    return os.path.exists("/proc/" + str(pid))


def main(argv):
    opts = parse_args(argv)

    if opts.list_sensors:
        print "\n".join(sorted(all_sensors))
        return 0

    if opts.daemon is not None:
        pid_file = "/tmp/sensors.pid"
        if opts.daemon == 'start':
            required_sensors = json.loads(opts.sensors_config.read())

            if "protocol_data" not in required_sensors:
                raise ValueError("No protocol data provided in config")

            def root_func():
                daemon_main(required_sensors, opts)

            daemon = Daemonize(app="perfcollect_app",
                               pid=pid_file,
                               action=root_func)
            daemon.start()
        elif opts.daemon == 'stop':
            if os.path.isfile(pid_file):
                pid = int(open(pid_file).read())
                if pid_running(pid):
                    os.kill(pid, signal.SIGTERM)

                time.sleep(0.1)

                if pid_running(pid):
                    os.kill(pid, signal.SIGKILL)

                if os.path.isfile(pid_file):
                    os.unlink(pid_file)
        elif opts.daemon == 'status':
            if os.path.isfile(pid_file):
                pid = int(open(pid_file).read())
                if pid_running(pid):
                    print "running"
                    return
            print "stopped"
        else:
            raise ValueError("Unknown daemon operation {}".format(opts.daemon))
    else:
        required_sensors = json.loads(opts.sensors_config.read())
        daemon_main(required_sensors, opts)
    return 0

if __name__ == "__main__":
    exit(main(sys.argv))
