#!/usr/bin/env python
# -*- coding: utf-8 -*-

import argparse
import requests
import time
import datetime

import modules.dm_api as dm


def print_replicas(replicas_data):
    print('Found replicas:')
    for dc in replicas_data:
        print(dc)
        for replic_num in replicas_data[dc]:
            print('Replic number: %s' % replic_num)
            for slot in replicas_data[dc][replic_num]:
                slot_data = instance_command(slot, 'get_info_server', disable_print=True)
                if 'result' in slot_data.keys() and slot_data['result']['search_enabled']:
                    sign = colored_string('green', '✓')
                elif 'result' in slot_data.keys() and not slot_data['result']['search_enabled']:
                    sign = colored_string('red', '✗')
                else:
                    sign = colored_string('red', 'u')

                print ('[%s][%s][%s] %s' % (dc, replic_num, sign.decode('utf-8'), slot))


def instance_command(slot, command, disable_print=False):
    try:
        host = slot.split(':')[0]
        port = slot.split(':')[1]
        request = 'http://%s:%d/?command=%s' % (host, int(port) + 3, command)
        resp = requests.get(request)
        if resp.status_code == 200:
            if not disable_print:
                print('HOST %s:%s STATUS: %s' % (host, port, resp.json().get('task_status')))
        else:
            print('Fail!')
            print(resp.json())
        return resp.json()
    except Exception:
        print('Problem with command %s for host %s port %s' % (command, host, port))
        return {}


def close_replica(replica, time_gap=15):
    print('[%s] Closing replica/location' % datetime.datetime.now())
    for instance in replica:
        instance_command(instance, 'disable_search')
        time.sleep(time_gap)
    print('[%s] Replica closed/location' % datetime.datetime.now())


def clear_index(replica, time_gap=15):
    print('[%s] Clearing index replica/location' % datetime.datetime.now())
    for instance in replica:
        instance_command(instance, 'clear_index')
        time.sleep(5)
        instance_command(instance, 'abort')
        time.sleep(time_gap)
    print('[%s] Index cleared' % datetime.datetime.now())


def open_replica(replica):
    print('[%s] Opening replica/location' % datetime.datetime.now())
    for instance in replica:
        instance_command(instance, 'enable_search')
    print('[%s] Replica is open/location' % datetime.datetime.now())


def colored_string(color, text):
    if 'green' in color:
        return '\033[92m' + text + '\033[0m'
    elif 'red' in color:
        return '\033[91m' + text + '\033[0m'
    else:
        return text


def parse_args(*args):
    options = argparse.ArgumentParser(prog='Service Uchenki',
                                      formatter_class=argparse.RawTextHelpFormatter,
                                      description="""
DESCRIPTION
Tool for SaaS teachings.
  1) Print information about service replicas
  3) Disable search on specified replica or dc
  4) Enable search on specified replica or dc
WARNING! Use with carefully.
""")

    options.add_argument('service_name', type=str,
                         help='Specifies service name')

    options.add_argument('--dc', dest='dc', default='', choices=['VLA', 'SAS', 'MAN'],
                         help='Specify DC for creating group or allocation')

    options.add_argument('--ctype', dest='ctype', required=True, choices=['prestable', 'stable',
                                                                          'stable_kv',
                                                                          'stable_middle_kv',
                                                                          'stable_gemini'],
                         help='Sets ctype of service')
    options.add_argument('-r', '--replic-num', dest='replic_num',
                         help='Specify replica number for action')
    options.add_argument('-t', '--time', dest='time_gap', type=int, default=15,
                         help='Specify time between closing instances')
    options.add_argument('-a', '--all', dest='all_replicas', action='store_true',
                         help='Specify all replicas. '
                              'This option may be used only with option --open')
    options.add_argument('--print', dest='print_action', action='store_true',
                         help='Print information about service replicas')
    options.add_argument('--open', action='store_true', dest='open_action',
                         help='Open specified replica by option -r, --dc or --all')
    options.add_argument('--close', dest='close_action', action='store_true',
                         help='Open specified replica by option -r or --dc')
    options.add_argument('--clear', dest='clear_index_action', action='store_true',
                         help='Clear index! CAUTION!')

    if args:
        opts = options.parse_args(args)
    else:
        opts = options.parse_args()
    return opts


def main(*args):
    options = parse_args(*args)
    service_dm = dm.DeployManager(options.service_name, options.ctype)

    # Check service and arguments
    if not service_dm.check_service_exists(strong_ctype=True):
        print('Service %s was not found in specified ctype: %s' % (options.service_name, options.ctype))
        return
    if (not options.replic_num and (options.open_action or options.close_action)) \
            and (not options.dc and (options.open_action or options.close_action)
                 and (not options.all_replicas and options.open_action)):
        print('For use option --open/--close you need specify replica number by ontion -r or '
              'datacenter by option --dc or --all (only for --open)')
        return

    # Collect information about replicas
    service_replicas = service_dm._get_replicas_data()
    replica_data = []
    if options.replic_num:
        for dc in service_replicas:
            for replica in service_replicas[dc]:
                if int(replica) == int(options.replic_num):
                    replica_data = service_replicas[dc][replica]
    elif options.dc:
        for replica in service_replicas[options.dc]:
            replica_data.extend(service_replicas[options.dc][replica])
    elif options.all_replicas and options.open_action:
        for dc in service_replicas:
            for replica in service_replicas[dc]:
                replica_data.extend(service_replicas[dc][replica])

    # Actions
    if options.print_action:
        print_replicas(service_replicas)
    if options.open_action:
        open_replica(replica_data)
    elif options.close_action and not options.all_replicas:
        close_replica(replica_data, time_gap=options.time_gap)
    elif options.clear_index_action and not options.all_replicas:
        clear_index(replica_data, time_gap=options.time_gap)

if __name__ == '__main__':
    main()
