import os
import subprocess
import requests
import json
import csv

from constants import InstallAction, get_migration_directory, ServerType

from common import can_edit_install
from common import can_install
from common import create_or_update_install_job
from common import fill_custom_command_profiles
from common import fill_default_region
from common import fill_regions
from common import fill_servers
from common import get_host
from common import get_return_url
from common import get_server_by_id
from common import get_server_list
from common import get_last_unfinished_install_action
from common import get_last_completed_or_failed_install_action

from database import DBSession
import datetime

from filters import get_datetime_string

from flask import Blueprint, jsonify, render_template, redirect, url_for, abort, request
from flask.ext.login import login_required, current_user
from flask import flash
from flask import send_from_directory
from werkzeug.utils import secure_filename

from models import Host, InstallJob, SystemOption, ConvertConfigJob, JobStatus
from models import logger

from wtforms import Form
from wtforms import StringField, SelectField, HiddenField, SelectMultipleField
from wtforms.validators import required

from smu_info_loader import IOSXR_URL

from utils import create_temp_user_directory, create_directory

from server_helper import TFTPServer, FTPServer, SFTPServer


NOX_64_BINARY = "nox-linux-64.bin"

# NOX_32_BINARY = "nox_linux_32bit_6.0.0v3.bin"
NOX_PUBLISH_DATE = "nox_linux.lastPublishDate"

asr9k_64_migrate = Blueprint('asr9k_64_migrate', __name__, url_prefix='/asr9k_64_migrate')


def get_config_conversion_path():
    temp_user_dir = create_temp_user_directory(current_user.username)
    config_conversion_path = os.path.normpath(os.path.join(temp_user_dir, "config_conversion"))
    create_directory(config_conversion_path)
    return config_conversion_path


def convert_config(db_session, http_request, template, schedule_form):

    config_form = init_config_form(db_session, http_request, get=True)

    success, err_msg = download_latest_config_migration_tool()
    if not success:
        return render_template(template, config_form=config_form,
                               input_filename="", err_msg=err_msg, schedule_form=schedule_form,
                               install_action=get_install_migrations_dict(),
                               server_time=datetime.datetime.utcnow())

    # check if the post request has the file part
    if 'file' not in http_request.files:
        flash('N
o file in 
request.')
        return render_template(template, config_form=config_form,
                               input_filename="", err_msg="Internal error - No file.",
                               schedule_form=schedule_form,
                               install_action=get_install_migrations_dict(),
                               server_time=datetime.datetime.utcnow(),)

    input_file = http_request.files['file']
    # if user does not select file, browser also
    # submit a empty part without filename
    if input_file.filename == '':
        flash('No selected file.')
        return render_template(template, config_form=config_form,
                               input_filename="", err_msg="Internal error - No selected file.",
                               schedule_form=schedule_form,
                               install_action=get_install_migrations_dict(),
                               server_time=datetime.datetime.utcnow(),)

    config_conversion_path = get_config_conversion_path()
    create_directory(config_conversion_path)

    if input_file:
        filename = secure_filename(input_file.filename)
        input_file.save(os.path.join(config_conversion_path, filename))

    return render_template(template, config_form=config_form,
                           input_filename=input_file.filename, err_msg="", schedule_form=schedule_form,
                           install_action=get_install_migrations_dict(),
                           server_time=datetime.datetime.utcnow())


@asr9k_64_migrate.route('/api/convert_config_file')
@login_required
def convert_config_file():
    filename = request.args.get('filename', '', type=str)

    filename = secure_filename(filename)

    config_conversion_path = get_config_conversion_path()

    db_session = DBSession()

    convert_config_job = ConvertConfigJob(file_path=os.path.join(config_conversion_path, filename),
                                          status='Preparing the conversion')
    db_session.add(convert_config_job)
    db_session.commit()

    job_id = convert_config_job.id

    return jsonify({'status': 'OK', 'job_id': job_id})


@asr9k_64_migrate.route('/api/get_config_conversion_progress')
@login_required
def get_config_conversion_progress():

    job_id = request.args.get('job_id', 0, type=int)

    db_session = DBSession()

    convert_config_job = db_session.query(ConvertConfigJob).filter(ConvertConfigJob.id == job_id).first()
    if convert_config_job is None:
        logger.error('Unable to retrieve Convert Config Job: %s' % job_id)
        return jsonify(status='Unable to retrieve job')
    return jsonify(status='OK', progress=convert_config_job.status)


@asr9k_64_migrate.route('/api/get_file')
@login_required
def get_file():
    which_file = request.args.get('file_number', 0, type=int)

    filename = request.args.get('filename', '', type=str)

    config_conversion_path = get_config_conversion_path()

    stripped_filename = get_stripped_filename(filename)

    output_html = stripped_filename + ".html"
    output_iox = stripped_filename + ".iox"
    output_cal = stripped_filename + ".cal"

    if which_file == 1:
        return send_from_directory(config_conversion_path,
                                   output_html, cache_timeout=0)
    elif which_file == 2:
        return send_from_directory(config_conversion_path,
                                   output_iox, cache_timeout=0)
    elif which_file == 3:
        return send_from_directory(config_conversion_path,
                                   output_cal, cache_timeout=0)

    return jsonify(**{'data': 'file does not exist.'})


@asr9k_64_migrate.route('/api/get_analysis')
@login_required
def process_config_conversion_output():
    filename = request.args.get('filename', '', type=str)

    config_conversion_path = get_config_conversion_path()

    stripped_filename = get_stripped_filename(filename)

    output_csv = stripped_filename + ".csv"
    html_file = stripped_filename + ".html"

    map_csv_category_to_final_category = {
        'KNOWN_SUPPORTED': 'supported',
        'KNOWN_UNSUPPORTED': 'unsupported',
        'UNKNOWN_UNSUPPORTED': 'unrecognized',
        'KNOWN_UNIMPLEMENTED': 'unimplemented',
        'ERROR_SYNTAX': 'syntaxerrors',
        'UNPROCESSED': 'unprocessed'

    }
    with open(os.path.join(config_conversion_path, html_file), 'w') as output_html:
        with open(os.path.join(config_conversion_path, secure_filename(filename)), 'r') as input_file:
            with open(os.path.join(config_conversion_path, output_csv), 'rb') as csvfile:
                output_html.write('<pre style="background-color:white;border:none;word-wrap:initial;">\n')
                reader = csv.reader(csvfile)
                last_category = ""
                for config_line in input_file:
                    next_row = reader.next()
                    if next_row and len(next_row) >= 2:

                        category = next_row[1].strip()
                        if category != last_category:
                            if last_category != "":
                                output_html.write('</div>')
                            html_class = map_csv_category_to_final_category.get(category)
                            output_html.write('<div class="' + html_class + '">\n')
                            last_category = category
                        output_html.write('<code>' + config_line.rstrip('\n') + '</code>\n')
                output_html.write('</div>\n')
                output_html.write('</pre>')
    return send_from_directory(config_conversion_path, html_file