from flask import Flask, session, render_template, redirect, url_for
from flask_bootstrap import Bootstrap5
from flask_wtf import FlaskForm, CSRFProtect
from wtforms import (StringField, SubmitField, TextAreaField, IntegerField, RadioField, HiddenField)
from vals import *
currOS = platform.platform()
if currOS.find('Windows') == 0:
    LOCALBASE = 'D:/website/'
else:
    LOCALBASE = '/mnt/d/website/'
import secrets
try:
    import readline
except ImportError:
    readline = None
# Bootstrap-Flask requires this line
app = Flask(__name__)
foo = secrets.token_urlsafe(16)
app.secret_key = foo
csrf = CSRFProtect(app)
bootstrap = Bootstrap5(app)

# GLOBALS
CONTRIBDIR = LOCALBASE + 'contributors/'
TEMPLATE = CONTRIBDIR + 'template.ft3'
# these will come from account data
my_enc_first = 'Sarge'
my_enc_last = 'Gerbode'
my_ed_first = 'Sarge'
my_ed_last = 'Gerbode'
myeditor = my_ed_first + ' ' + my_ed_last
myencoder = my_enc_first + ' ' + my_enc_last
my_dir = my_enc_last + my_enc_first[0]

def get_instrument_suggestions():
    return sorted(
        {re.sub(r'\s+', ' ', inst.strip()) for inst in liInsts if inst and inst.strip()},
        key=str.lower
    )

def get_type_suggestions():
    return sorted(
        {re.sub(r'\s+', ' ', music_type.strip()) for music_type in liTypes if music_type and music_type.strip()},
        key=str.lower
    )

def get_name_suggestions():
    return sorted(
        {re.sub(r'\s+', ' ', name.strip()) for name in liNames if name and name.strip()},
        key=str.lower
    )

def get_source_suggestions():
    return sorted(
        {
            re.sub(r'\s+', ' ', source.strip())
            for source in liSources
            if source and source.strip()
        },
        key=str.lower
    )

def _safe_filename_part(value):
    if not value:
        return ''
    value = value.strip()
    if value == '':
        return ''
    value = re.sub(r'\.ft3$', '', value, flags=re.IGNORECASE)
    value = re.sub(r'[\\/:*?"<>|]+', ' ', value)
    value = re.sub(r'\s+', '_', value)
    value = re.sub(r'_+', '_', value)
    value = value.strip(' ._')
    return value

def _generate_output_filename(input_form, diData):
    parts = []
    for value in (
        input_form.title.data,
        input_form.composer.data,
        input_form.document.data,
        diData.get('infile', '')
    ):
        safe_value = _safe_filename_part(value)
        if safe_value and safe_value.lower() != 'template':
            parts.append(safe_value)
        if len(parts) == 2:
            break
    if parts:
        filename = '_'.join(parts)
    else:
        filename = 'new_fronimo_file'
    return filename[:60].rstrip(' ._') or 'new_fronimo_file'

def get_values_from_form(input_form):
    diData = session.get('initial_data') or session.get('data', {})
    output_name = input_form.outputfile.data.strip()
    if output_name == '':
        output_name = _generate_output_filename(input_form, diData)
    diData = {
    'name': input_form.myname.data, \
            'infile': diData['infile'], \
    'title': input_form.title.data, \
    'subtitle':input_form.subtitle.data, \
    'composer': input_form.composer.data, \
    'orig': input_form.composer0.data, \
    'ensemble': input_form.ensemble.data, \
    'part': input_form.part.data, \
    'key': input_form.key.data, \
    'difficulty': input_form.difficulty.data, \
    'type': input_form.type.data, \
    'source': input_form.source.data,\
    'document': input_form.document.data, \
    'volume': input_form.volume.data, \
    'page': input_form.page.data, \
    'date': input_form.date.data, \
    'section': input_form.section.data, \
    'editor': input_form.editor.data, \
    'encoder': input_form.encoder.data, \
    'intabulator': input_form.intabulator.data, \
    'arranger': input_form.arranger.data, \
    'contributor': input_form.contributor.data,\
    'remarks': input_form.remarks.data, \
    'outfile': add_prefix_and_suffix(output_name)
    }
    return(diData)

def add_defaults_to_form(diDefault):
    class OutputForm(FlaskForm):
        allow_new_source = HiddenField(default = '')
        allow_new_document = HiddenField(default = '')
        outputfile = StringField('Output file (Required). Will overwrite an existing file:', \
        default = diDefault['outputfile'], \
        validators = [Optional(), Length(0, 60), output_val])
        myname = StringField('Full name (first and last):', \
        default = diDefault['encoder'], \
        validators = [Length(1, 40), name_val])
        title = StringField('Title:', default = diDefault['title'], \
        validators = [InputRequired(), Length(3, 40)])
        subtitle = StringField('Subtitle (optional):',\
        default = diDefault['subtitle'], \
        validators = [Optional(), Length(3, 40)])
        composer = StringField('Composer:',\
        default = diDefault['composer'], \
        validators = [InputRequired(), Length(2,40), composer_val], \
        render_kw={'autocomplete': 'off'})
        composer0 = StringField('Original composer (optional):', \
        default = diDefault['composer0'], \
        validators = [Optional(), Length(2,40), composer_val], \
        render_kw={'autocomplete': 'off'})
        ensemble = StringField('Ensemble (comma-separated list of instruments or voices):', \
        default = diDefault['ensemble'], \
        validators = [InputRequired(), ensemble_val], \
        render_kw={'autocomplete': 'off'})
        part = StringField('Part (optional: "score", or comma-separated list of instruments or voices):', \
        default = diDefault['part'], \
        validators = [Optional(), part_val], \
        render_kw={'autocomplete': 'off'})
        key = StringField('Comma-separated list of keys, like Abm, EM:', \
        default = diDefault['key'], \
        validators = [InputRequired(), key_val])
        difficulty = RadioField('Difficulty (choose one):', \
        choices=[('0', 'Beginner'), ('1', 'Easy'), ('2', 'Medium'), ('3', 'Challenging'), ('4', 'Hard'), ('5', 'Virtuoso')], \
        default = str(diDefault['difficulty']), \
        validators = [InputRequired()])
        type = StringField('Musical Type[s]: Comma separated list, like pavane, galliard', \
        default = diDefault['type'], \
        validators = [InputRequired(), type_val], \
        render_kw={'autocomplete': 'off'})
        source = StringField('Source: Name, or if a MS, library siglum + : + library name[s]', \
        default = diDefault['source'], \
        validators = [InputRequired(), source_val], \
        render_kw={'autocomplete': 'off'})
        document = StringField('Document: If a book, the title; if a ms, call sign (if any) + : + ms name', \
        default = diDefault['document'], \
        validators = [InputRequired(), Length(5, 40), document_val])
        volume = StringField('Volume # (if any):', \
        default = diDefault['volume'], \
        validators = [Optional(), volume_val])
        date = StringField('Year 1000 to now. Can use "c" or "c.", like c1605 or c.1605', \
        default = diDefault['date'], \
        validators = [InputRequired(),  Regexp('(?:c\\.?)?[12][0-9][0-9][0-9]', \
)])
        page = StringField('Page reference: use p. or f. for a single page, or pp./ff. for a comma-separated list like ff.135,285b.', \

        default = diDefault['page'], \
        validators = [InputRequired(), page_val]) 
        section = StringField('Section Name (optional): Must start with a number + . + space, like 12. Galliard', \
        default = diDefault['section'], \
        validators = [ Optional(), section_val])
        editor = StringField('Editor (required):', \
        default = diDefault['editor'], \
        validators = [InputRequired(), Length(10, 40)])
        encoder = StringField('Encoder (required):', \
        default = diDefault['encoder'], \
        validators = [InputRequired(), Length(10, 40)])
        intabulator = StringField('Intabulator (optional):', \
        default = diDefault['intabulator'], \
        validators = [Optional(), Length(10, 40)])
        arranger = StringField('Arranger (optional):', \
        default = diDefault['arranger'], \
        validators = [Optional(), Length(10, 40)])
        contributor = StringField('Contributor (optional):', \
        default = diDefault['contributor'], \
        validators = [Optional(), Length(10, 40)])
        remarks = TextAreaField('Remarks: (optional)', \
        default = diDefault['remarks'], \
        validators = [Optional()])
        submit = SubmitField('Submit')
        btn_cancel = SubmitField(label='Cancel', \
        render_kw={'formnovalidate': True})
    return OutputForm()

class FileForm(FlaskForm):
    inputfile = StringField('Name of file to edit: ', \
    default = '', validators = [Length(0,40), input_val])
    submit = SubmitField('Submit')
    btn_directory= SubmitField(label='Directory', \
    render_kw={'formnovalidate': True})
    btn_cancel=SubmitField(label='Cancel', \
    render_kw={'formnovalidate': True})
