import json
import logging

from datetime import datetime
from collections import OrderedDict

from wurker.settings import conf
from wurker.ui.auth import login_required
from wurker import ShowCommand, StatusCommand

from flask import Blueprint, render_template
from werkzeug.exceptions import abort


bp = Blueprint('index', __name__)

logger = logging.getLogger('gunicorn.error')


@bp.route('/')
@bp.route('/drone/<drone_id>')
@login_required
def index(drone_id:str=''):
    """Get the Queen's Court view, for the Queen, herself, or one of her Drones."""

    if not conf.is_queen:
        return None, 404

    drones = [drone_id] if drone_id else []

    # Will need the Queen's status for Node selectbox, even if this is a Drone
    statuscmd = StatusCommand()
    queen = statuscmd.run(return_result=True)

    if not queen:
        return None, 404

    # Get this Wurker's status (Queen or Drone)
    status = statuscmd.run(drones=drones, return_result=True)

    info = (
        status if not drone_id
        else {} if not status or drone_id not in status
        else status[drone_id]
    )

    if not info:
        return None, 404

    if "local_db" in info and info["local_db"]["password"]:
        info["local_db"]["password"] = "****"

    if "remote_db" in info and info["remote_db"]["password"]:
        info["remote_db"]["password"] = "****"

    infoJson = json.dumps(info, sort_keys=True, indent=2)

    # Then get 'show' subcommand (Queen or Drone) with sections strictly sorted
    showcmd = ShowCommand()
    show = showcmd.run("all", drones=drones, return_result=True)

    bees = (
        show if not drone_id
        else {} if not show or drone_id not in show
        else show[drone_id]
    )

    sort_order = ["supervised", "scheduled", "ondemand", "orphaned", "disabled",]
    unsorted = {section:crons for section, crons in bees.items() if len(crons)}

    sections = OrderedDict()
    for section in [s for s in sort_order if s in unsorted]:
        sections[section] = unsorted[section]

    # UI bees need JSON args, not Python like we got with return_result=True
    for section, crons in sections.items():
        for cron, bees in crons.items():
            for slug, bee in bees.items():
                bee["args"] = json.dumps(bee["args"])

    # Then get the show hive data
    hives = showcmd.run("hive", drones=drones, return_result=True)

    hive = (
        hives if not drone_id
        else {} if not hives or drone_id not in hives
        else hives[drone_id]
    )

    # Assemble Hive data and add Ondemand into it, deleting from sections
    hive_data = {
        "hive": hive,
        "ondemand": sections.get("ondemand", {})
    }
    if "ondemand" in sections:
        del sections["ondemand"]

    # We also want the Crons and Commands for separate UI purposes
    crons = showcmd.run("cron", drones=drones, return_result=True)

    cron_data = (
        crons if not drone_id
        else {} if not crons or drone_id not in crons
        else crons[drone_id]
    )

    # Need this for modal Edit Cron form
    cron_dict = {v["slug"]:v for v in cron_data}
    cronJson = json.dumps(cron_dict, sort_keys=True, indent=2)

    cmds = showcmd.run("command", drones=drones, return_result=True)

    cmd_data = (
        cmds if not drone_id
        else {} if not cmds or drone_id not in cmds
        else cmds[drone_id]
    )

    # Need this for modal Edit Command form
    cmd_dict = {v["slug"]:v for v in cmd_data}
    commandJson = json.dumps(cmd_dict, sort_keys=True, indent=2)

    # We also want the "widowed" Crons and Commands for UI purposes
    crons = showcmd.run("cron", widowed=True, drones=drones, return_result=True)

    cron_widowed = (
        crons if not drone_id
        else {} if not crons or drone_id not in crons
        else crons[drone_id]
    )


    cmds = showcmd.run("command", widowed=True, drones=drones, return_result=True)

    cmd_widowed = (
        cmds if not drone_id
        else {} if not cmds or drone_id not in cmds
        else cmds[drone_id]
    )

    # Compose the result and render it
    result = {
        "page": info.get("name", None),              # For title
        "app_id": info.get("app_id", None),          # For API requests
        "is_queen": info.get("is_queen", None),      # For API requests, and just so you know
        "drones": queen.get("drones", None),         # For everything. They're everywhere.
        "env": info.get("env", None),                # Because DON'T FUCK UP PRODUCTION!
        "hiveData": hive_data,                       # UI display: What's abuzz?
        "cronData": cron_data,                       # For select options
        "commandData": cmd_data,                     # For select options
        "cronWidowed": cron_widowed,                 # For select options
        "commandWidowed": cmd_widowed,               # For select options
        "sections": sections,                        # For select options
        "infoJson": infoJson,                        # For node status
        "cronJson": cronJson,                        # For modal edit form
        "commandJson": commandJson,                  # For modal edit form
        "thisYear": datetime.now().strftime('%Y'),   # For copyright
    }

    return render_template('index.html', **result)
