#!/usr/bin/env python
from time import strftime
import argparse
import hashlib
import shutil
import yaml
import sys
import os

# Hack to set the proper sys.path. Overcomes the export PYTHONPATH pain.
sys.path[:] = map(os.path.abspath, sys.path)
sys.path.insert(0, os.path.abspath(os.getcwd()))

class OBAdmin(object):
    def __init__(self, config_file):
        with open(config_file) as f:
            self.config = yaml.safe_load(f)
        self.input_dir = self.config['main']['input_dir']
        self.deck_dir = self.config['main']['deck_dir']
        self.policy_file = self.config['main']['policy_file']
    
    def digest(self, file_path):
        with open(file_path) as f:
            file_hash = hashlib.sha256(f.read())
        return file_hash.hexdigest()
    
    def read_descriptor(self):
        descriptor = { 
            'date': strftime("%Y-%m-%dT%H:%M:%S"),
        }
        descriptor['name'] = raw_input('name: ')
        descriptor['description'] = raw_input('description: ')
        descriptor['version'] = raw_input('version: ')
        descriptor['author'] = raw_input('author: ')
        
        return descriptor
    
    def add_deck(self, file_path):
        digest = self.digest(file_path)
        dst_path = os.path.join(self.deck_dir, digest)
        if os.path.exists(dst_path):
            print "Deck already present at %s" % dst_path
            return
        shutil.copyfile(file_path, dst_path)
        descriptor = self.read_descriptor()
        descriptor['id'] = digest
        with open(dst_path + '.desc', 'w+') as f:
            yaml.dump(descriptor, f)

        self.add_deck_to_policy(file_path)

    def add_deck_to_policy(self, deck_path):
        with open(self.policy_file) as f:
            policy = yaml.safe_load(f)
        with open(deck_path) as f:
            deck = yaml.safe_load(f)

        def test_in_policy(test_name):
            for test in policy['nettest']:
                if test['name'] == test_name:
                    return True
            return False

        for test in deck:
            test_name = test['options']['test_file'].split('/')[-1]
            if not test_in_policy(test_name):
                policy['nettest'].append({'name': test_name, 'version': '0.1'})

        with open(self.policy_file, 'w+') as f:
            yaml.dump(policy, f)

    def add_input_to_policy(self, digest):
        with open(self.policy_file) as f:
            policy = yaml.safe_load(f)
        policy['input'].append({'id': digest})
        with open(self.policy_file, 'w+') as f:
            yaml.dump(policy, f)

    def add_input(self, file_path):
        digest = self.digest(file_path)
        dst_path = os.path.join(self.input_dir, digest)
        if os.path.exists(dst_path):
            print "Input already present at %s" % dst_path
            return
        shutil.copyfile(file_path, dst_path)
        descriptor = self.read_descriptor()
        descriptor['id'] = digest
        with open(dst_path + '.desc', 'w+') as f:
            yaml.dump(descriptor, f)
        self.add_input_to_policy(digest)

parser = argparse.ArgumentParser(description='Administer oonib')
parser.add_argument('-c', '--config', default='oonib.conf',
        help="Specify the config file to read from")

subparsers = parser.add_subparsers(dest='command',
        help='Run the specified operation on the current oonib installation')
parser_add_input = subparsers.add_parser('add_input', 
        help="add an input to the list of inputs offerred by this collector")
parser_add_input.add_argument('file', help="path to the input to add")

parser_add_deck = subparsers.add_parser('add_deck', 
        help="add a deck the list of decks offerred by this collector")
parser_add_deck.add_argument('file', help="path to the deck to add")

args = parser.parse_args()

ob_admin = OBAdmin(args.config)

if args.command == 'add_deck':
    ob_admin.add_deck(args.file)
elif args.command == 'add_input':
    ob_admin.add_input(args.file)
