#!/usr/bin/env python

from __future__ import absolute_import, print_function

import argparse
import json
import sys

from changes.config import create_app, db
from changes.constants import IMPLEMENTATION_CHOICES
from changes.models.plan import Plan, PlanStatus
from changes.models.project import Project
from changes.models.step import Step


app = create_app()
app_context = app.app_context()
app_context.push()

parser = argparse.ArgumentParser(description='Manage plans')

subparsers = parser.add_subparsers(dest='command')

parser_add = subparsers.add_parser('add', help='add plan')
parser_add.add_argument('--label', dest='label', help='plan label')
parser_add.add_argument('--data', dest='data', help='plan data')

parser_edit = subparsers.add_parser('edit', help='edit plan')
parser_edit.add_argument('id', help='plan ID')
parser_edit.add_argument('--label', dest='label', help='plan label')
parser_edit.add_argument('--data', dest='data', help='plan data')
parser_edit.add_argument('--active', dest='active', action='store_true')
parser_edit.add_argument('--inactive', dest='active', action='store_false')

parser_list = subparsers.add_parser('list', help='list plans')

parser_projects = subparsers.add_parser(
    'projects', help='manage plan projects')
options_subparsers = parser_projects.add_subparsers(dest='project_command')

parser_projects_add = options_subparsers.add_parser(
    'add', help='add plan project')
parser_projects_add.add_argument('id', help='plan ID')
parser_projects_add.add_argument('project', help='project ID or slug')

parser_projects_delete = options_subparsers.add_parser(
    'delete', help='remove plan project')
parser_projects_delete.add_argument('id', help='plan ID')
parser_projects_delete.add_argument('project', help='project ID or slug')

parser_projects_list = options_subparsers.add_parser(
    'list', help='list plan projects')
parser_projects_list.add_argument('id', help='plan ID')

parser_steps = subparsers.add_parser('steps', help='manage plan steps')
options_subparsers = parser_steps.add_subparsers(dest='step_command')

parser_steps_add = options_subparsers.add_parser('add', help='add plan step')
parser_steps_add.add_argument('id', help='step ID')
parser_steps_add.add_argument(
    '--implementation', dest='implementation', help='step implementation',
    required=True, choices=IMPLEMENTATION_CHOICES)
parser_steps_add.add_argument(
    '--order', dest='order', help='step order',
    required=True, type=int)
parser_steps_add.add_argument('--data', dest='data', help='step data')

parser_steps_delete = options_subparsers.add_parser(
    'delete', help='remove plan step')
parser_steps_delete.add_argument('id', help='plan ID')
parser_steps_delete.add_argument('step', help='step ID')

parser_steps_list = options_subparsers.add_parser(
    'list', help='list plan steps')
parser_steps_list.add_argument('id', help='plan ID')

parser_steps_clear = options_subparsers.add_parser(
    'clear', help='clear plan steps')
parser_steps_clear.add_argument('id', help='plan ID')

args = parser.parse_args()


def abort():
    print('Aborted!')
    sys.exit(1)


def get_plan(id_):
    result = Plan.query.get(id_)

    if not result:
        print("Plan not found")
        sys.exit(1)

    return result


def get_project(id_):
    if len(id_) == 40:
        # assume its a uuid
        project = Project.query.get(id_)
    else:
        project = Project.query.filter_by(slug=id_).first()

    if not project:
        print("Project not found")
        sys.exit(1)

    return project


def get_step(id_):
    result = Step.query.get(id_)

    if not result:
        print("Step not found")
        sys.exit(1)

    return result


if args.command == 'add':
    label = args.label or raw_input('Plan label? ') or abort()
    data = json.loads(args.data or '{}')

    plan = Plan(
        label=label,
        data=data,
    )

    db.session.add(plan)

    print("Created new plan with ID {%s}" % (
        plan.id,
    ))

elif args.command == 'edit':
    plan = get_plan(args.id)

    if args.label:
        plan.label = args.label
    if args.data is not None:
        plan.data = json.loads(args.data)
    if args.active:
        plan.status = PlanStatus.active
    elif args.active is False:
        plan.status = PlanStatus.inactive

    db.session.add(plan)

    print("Saved plan with ID {%s}" % (
        plan.id,
    ))


elif args.command == 'list':
    for plan in Plan.query.order_by(Plan.label.asc()):
        print('{0} {1}'.format(plan.id, plan.label))

elif args.command == 'steps':
    if args.step_command == 'add':
        plan = get_plan(args.id)

        step = Step(
            plan=plan,
            order=args.order,
            implementation=args.implementation,
            data=json.loads(args.data or '{}'),
        )
        db.session.add(step)

        print("Added step %s (%s) to %s" % (
            step.order, step.implementation, plan.id))

    if args.step_command == 'delete':
        plan = get_plan(args.id)
        step = get_step(args.step)

        Step.query.filter(
            Step.id == step.id,
        ).delete(synchronize_session=False)

        print("Removed step %s (%s) from %s" % (
            step.order, step.implementation, plan.id))

    if args.step_command == 'list':
        plan = get_plan(args.id)

        for step in plan.steps:
            print('{0} {1} {2}'.format(
                step.id, step.order, step.implementation))

    if args.step_command == 'clear':
        plan = get_plan(args.id)

        Step.query.filter(
            Step.plan_id == plan.id,
        ).delete(synchronize_session=False)

        print("Removed all steps from %s" % (plan.id,))

db.session.commit()
