import logging
import asyncio

from aiohttp import web, hdrs

import printer_fields
from web_interface.auth import check_auth
from web_interface.printer_profiles_handlers import get_vid_pid_from_request

ATTEMPTS = 3

def get_required_and_auth_fields(vid, pid, profiles):
    filter_list = [vid, pid]
    filter_dict = {'VID': vid, 'PID': pid}
    required_fields = set()
    auth_fields = set()
    for profile in profiles:
        if filter_list in profile.get('vids_pids', []):
            if 'network_detect' in profile:
                for field in profile['network_detect'].get('required_fields', []):
                    if field:
                        required_fields.add(str(field))
        for connection in profile.get('v2', {}).get('connections', []):
            if filter_dict in connection.get('ids'):
                for field in connection.get('auth_fields', []):
                    field_id = field.get('id')
                    if field_id:
                        auth_fields.add(str(field_id))
    internal_field_keys = {'IP'}
    for req_dict in printer_fields.REQUIRED_FIELDS:
        if req_dict['id'] in required_fields:
            internal_field_keys.add(req_dict['internal'])
    for auth_dict in printer_fields.AUTH_FIELDS:
        if auth_dict['id'] in auth_fields:
            internal_field_keys.add(auth_dict['internal'])
    return internal_field_keys


async def get_all_edit_fields(request):
    vid, pid = await get_vid_pid_from_request(request)
    profiles = request.app['3dp_app'].user_login.profiles
    return web.json_response(tuple(get_required_and_auth_fields(vid, pid, profiles)))


async def edit_printer(request):
    check_auth(request)
    logger = logging.getLogger('edit_printer')
    if request.content_type == 'application/json':
        post_data = await request.json()
    else:
        post_data = await request.post()
    args = {}
    args.update(post_data)
    printer_id = request.query.get('printer_id')
    if 'VID' not in args or 'PID' not in args or 'SNR' not in args:
        try:
            args['VID'], args['PID'], args['SNR'] = printer_id.strip().split('_', 2)
            try:
                args['SNR'] = args['SNR'].replace('_', '.')
            except:
                pass
        except (KeyError, ValueError, TypeError) as e:
            logger.error('No printer id getting error:' + str(e))
            raise web.HTTPBadRequest(text='No printer id found in post or query')
    # logger.info('Edit args: ' + str(args))
    # logger.info('Printer id: ' + str(printer_id))
    for _ in range(ATTEMPTS):
        for pi in request.app['3dp_app'].printer_interfaces:
            for key in ('VID', 'PID', 'SNR'):
                # logger.info(f"{key} Pi/Post: {pi.usb_info[key]}/{args[key]}")
                if pi.usb_info[key] != args[key]:
                    break
            else:
                if request.method == hdrs.METH_GET:
                    all_auth_fields = get_required_and_auth_fields(pi.usb_info['VID'], \
                            pi.usb_info['PID'], (pi.printer_profile, ))
                    if all_auth_fields:
                        existing_fields = pi.edit_printer()
                        for field in all_auth_fields:
                            if field not in existing_fields:
                                existing_fields[field] = None
                        return web.json_response(data=existing_fields)
                if request.method == hdrs.METH_POST:
                    if pi.edit_printer(args):
                        text = 'Success'
                    else:
                        text = 'Edit failed'
                    raise web.HTTPFound('/network_printer_list_page', text=text)
                    # raise web.HTTPFound('/pages/edit_printer?printer_id=' + printer_id, text=text)
        await asyncio.sleep(1.5)
    raise web.HTTPNotFound(text='No printer with that id')
