import copy
import itertools
import logging
import os
from pathlib import Path
import html
import boto3
import time

import json

import gradio
import requests
import base64
from urllib.parse import urljoin

import gradio as gr

import utils
from aws_extension.auth_service.simple_cloud_auth import cloud_auth_manager
from aws_extension.cloud_api_manager.api_manager import api_manager
from aws_extension.sagemaker_ui_utils import create_refresh_button_by_user

from modules import shared, scripts
from modules.ui import create_refresh_button
from modules.shared import opts
from modules.ui_components import FormRow, FormColumn, FormGroup, ToolButton, FormHTML
from utils import get_variable_from_json
from utils import upload_file_to_s3_by_presign_url, upload_multipart_files_to_s3_by_signed_url
from requests.exceptions import JSONDecodeError
from datetime import datetime
import math
import re

import asyncio
import nest_asyncio

from utils import cp, tar, rm

logger = logging.getLogger(__name__)
logger.setLevel(utils.LOGGING_LEVEL)

None_Option_For_On_Cloud_Model = "don't use on cloud inference"

inference_job_dropdown = None
textual_inversion_dropdown = None
hyperNetwork_dropdown = None
lora_dropdown = None
# sagemaker_endpoint = None
modelmerger_merge_on_cloud = None
interrogate_clip_on_cloud_button = None
interrogate_deep_booru_on_cloud_button = None

primary_model_name = None
secondary_model_name = None
tertiary_model_name = None

# TODO: convert to dynamically init the following variables
txt2img_inference_job_ids = []

sd_checkpoints = []
textual_inversion_list = []
lora_list = []
hyperNetwork_list = []
ControlNet_model_list = []

# Initial checkpoints information
checkpoint_info = {}
checkpoint_type = ["Stable-diffusion", "embeddings", "Lora", "hypernetworks", "ControlNet", "VAE"]
checkpoint_name = ["stable_diffusion", "embeddings", "lora", "hypernetworks", "controlnet", "VAE"]
stable_diffusion_list = []
embeddings_list = []

hypernetworks_list = []
controlnet_list = []
for ckpt_type, ckpt_name in zip(checkpoint_type, checkpoint_name):
    checkpoint_info[ckpt_type] = {}
# get api_gateway_url
api_gateway_url = get_variable_from_json('api_gateway_url')
api_key = get_variable_from_json('api_token')

start_time_picker_img_value = None
end_time_picker_img_value = None
start_time_picker_txt_value = None
end_time_picker_txt_value = None

txt_task_type = None
txt_status = None
txt_endpoint = None
txt_checkpoint = None

img_task_type = None
img_status = None
img_endpoint = None
img_checkpoint = None

show_all_inference_job = False

modelTypeMap = {
    'SD Checkpoints': 'Stable-diffusion',
    'Textual Inversion': 'embeddings',
    'LoRA model': 'Lora',
    'ControlNet model': 'ControlNet',
    'Hypernetwork': 'hypernetworks',
    'VAE': 'VAE'
}

def plaintext_to_html(text):
    text = "
" + "
\n".join([f"{html.escape(x)}" for x in text.split('\n')]) + "
"
    return text

def server_request_post(path, params):
    api_gateway_url = get_variable_from_json('api_gateway_url')
    # Check if api_url ends with '/', if not append it
    if not api_gateway_url.endswith('/'):
        api_gateway_url += '/'
    api_key = get_variable_from_json('api_token')
    headers = {
        "x-api-key": api_key,
        "Content-Type": "application/json"
    }
    list_endpoint_url = f'{api_gateway_url}{path}'
    response = requests.post(list_endpoint_url, json=params, headers=headers)
    return response

def get_s3_file_names(bucket, folder):
    """Get a list of file names from an S3 bucket and folder."""
    s3 = boto3.resource('s3')
    bucket = s3.Bucket(bucket)
    objects = bucket.objects.filter(Prefix=folder)
    names = [obj.key for obj in objects]
    return names

def get_current_date():
    today = datetime.today()
    formatted_date = today.strftime('%Y-%m-%d')
    return formatted_date

def server_request(path):
    api_gateway_url = get_variable_from_json('api_gateway_url')
    # Check if api_url ends with '/', if not append it
    if not api_gateway_url.endswith('/'):
        api_gateway_url += '/'
    api_key = get_variable_from_json('api_token')
    headers = {
        "x-api-key": api_key,
        "Content-Type": "application/json"
    }
    list_endpoint_url = f'{api_gateway_url}{path}'
    response = requests.get(list_endpoint_url, headers=headers)
    return response

def datetime_to_short_form(datetime_str):
    dt = datetime.strptime(datetime_str, "%Y-%m-%d %H:%M:%S.%f")
    short_form = dt.strftime("%Y-%m-%d-%H-%M-%S")
    return short_form

def query_page_inference_job_list(task_type: str, status: str, endpoint: str, checkpoint: str, is_img2img: bool,
                                  show_all: bool):
    global show_all_inference_job
    show_all_inference_job = show_all
    if is_img2img:
        global img_task_type
        img_task_type = task_type
        global img_status
        img_status = status
        global img_endpoint
        img_endpoint = endpoint
        global img_checkpoint
        img_checkpoint = checkpoint
        opt_type = 'img2img'
        logger.debug(f"{opt_type} {img_task_type} {img_status} {img_endpoint} {img_checkpoint} {show_all}")
        return query_inference_job_list(task_type, status, endpoint, checkpoint, opt_type)
    else:
        global txt_task_type
        txt_task_type = task_type
        global txt_status
        txt_status = txt_status
        global txt_endpoint
        txt_endpoint = endpoint
        global txt_checkpoint
        txt_checkpoint = checkpoint
        opt_type = 'txt2img'
        logger.debug(f"{opt_type} {txt_task_type} {txt_status} {txt_endpoint} {txt_checkpoint} {show_all}")
        return query_inference_job_list(task_type, status, endpoint, checkpoint, opt_type)

def query_img_inference_job_list(task_type: str, status: str, endpoint: str, checkpoint: str):
    opt_type = 'img2img'
    global img_task_type
    img_task_type = task_type
    global img_status
    img_status = status
    global img_endpoint
    img_endpoint = endpoint
    global img_checkpoint
    img_checkpoint = checkpoint
    return query_inference_job_list(task_type, status, endpoint, checkpoint, opt_type)

def query_txt_inference_job_list(task_type: str, status: str, endpoint: str, checkpoint: str):
    opt_type = 'txt2img'
    global txt_task_type
    txt_task_type = task_type
    global txt_status
    txt_status = status
    global txt_endpoint
    txt_endpoint = endpoint
    global txt_checkpoint
    txt_checkpoint = checkpoint

    return query_inference_job_list(task_type, status, endpoint, checkpoint, opt_type)

def query_inference_job_list(task_type: str = '', status: str = '',
                             endpoint: str = '', checkpoint: str = '', opt_type: str = ''):
    logger.debug(
        f"query_inference_job_list start！！{status},{task_type},{endpoint},{checkpoint},{start_time_picker_txt_value},{end_time_picker_txt_value} {show_all_inference_job}")
    try:
        body_params = {}
        if status:
            body_params['status'] = status
        if task_type:
            body_params['task_type'] = task_type
        if opt_type == 'txt2img':
            if start_time_picker_txt_value:
                body_params['start_time'] = start_time_picker_txt_value
            if end_time_picker_txt_value:
                body_params['end_time'] = end_time_picker_txt_value
        elif opt_type == 'img2img':
            if start_time_picker_img_value:
                body_params['start_time'] = start_time_picker_img_value
            if end_time_picker_img_value:
                body_params['end_time'] = end_time_picker_img_value
        if endpoint:
            endpoint_name_array = endpoint.split("+")
            if len(endpoint_name_array) > 0:
                body_params['endpoint'] = endpoint_name_array[0]
        if checkpoint:
            body_params['checkpoint'] = checkpoint
        body_params['limit'] = -1 if show_all_inference_job else 10
        response = server_request_post(f'inference/query-inference-jobs', body_params)
        r = response.json()
        logger.debug(r)
        if r:
            txt2img_inference_job_ids.clear()  # Clear the existing list before appending new values
            temp_list = []
            for obj in r:
                if obj.get('completeTime') is None:
                    complete_time = obj.get('startTime')
                else:
                    complete_time = obj.get('completeTime')
                status = obj.get('status')
                task_type = obj.get('taskType', 'txt2img')
                inference_job_id = obj.get('InferenceJobId')
                combined_string = f"{complete_time}-->{task_type}-->{status}-->{inference_job_id}"
                temp_list.append((complete_time, combined_string))
            # Sort the list based on completeTime in ascending order
            sorted_list = sorted(temp_list, key=lambda x: x[0], reverse=False)
            # Append the sorted combined strings to the txt2img_inference_job_ids list
            for item in sorted_list:
                txt2img_inference_job_ids.append(item[1])
            # inference_job_dropdown.update(choices=txt2img_inference_job_ids)
            return gr.Dropdown.update(choices=txt2img_inference_job_ids)
        else:
            logger.info("The API response is empty.")
            return gr.Dropdown.update(choices=[])
    except Exception as e:
        logger.error("Exception occurred when fetching inference_job_ids")
        logger.error(e)
        return gr.Dropdown.update(choices=[])

# def get_inference_job_list(txt2img_type_checkbox=True, img2img_type_checkbox=True, interrogate_type_checkbox=True):
#     global txt2img_inference_job_ids
#     try:
#         txt2img_inference_job_ids.clear()  # Clear the existing list before appending new values
#         response = server_request('inference/list-inference-jobs')
#         r = response.json()
#         logger.debug(f"response: {response.json()}")
#         filter_checkbox = False
#         selected_types = []
#         if txt2img_type_checkbox:
#             selected_types.append('txt2img')
#             filter_checkbox = True
#         if img2img_type_checkbox:
#             selected_types.append('img2img')
#             filter_checkbox = True
#         if interrogate_type_checkbox:
#             selected_types.append('interrogate_deepbooru')
#             filter_checkbox = True
#         logging.debug(f"selected_types: {selected_types}")
#         if r:
#             txt2img_inference_job_ids.clear()  # Clear the existing list before appending new values
#             temp_list = []
#             for obj in r:
#                 if obj.get('completeTime') is None:
#                     complete_time = obj.get('startTime')
#                 else:
#                     complete_time = obj.get('completeTime')
#                 status = obj.get('status')
#                 task_type = obj.get('taskType', 'txt2img')
#                 inference_job_id = obj.get('InferenceJobId')
#                 if filter_checkbox and task_type not in selected_types:
#                     continue
#                 combined_string = f"{complete_time}-->{task_type}-->{status}-->{inference_job_id}"
#                 temp_list.append((complete_time, combined_string))
#
#             # Sort the list based on completeTime in ascending order
#             sorted_list = sorted(temp_list, key=lambda x: x[0], reverse=False)
#
#             # Append the sorted combined strings to the txt2img_inference_job_ids list
#             for item in sorted_list:
#                 txt2img_inference_job_ids.append(item[1])
#             # inference_job_dropdown.update(choices=txt2img_inference_job_ids)
#             return gr.Dropdown.update(choices=txt2img_inference_job_ids)
#         else:
#             logger.debug("The API response is empty.")
#             return gr.Dropdown.update(choices=[])
#
#     except Exception as e:
#         logger.error("Exception occurred when fetching inference_job_ids")
#         return gr.Dropdown.update(choices=[])

def get_inference_job(inference_job_id):
    response = server_request(f'inference/get-inference-job?jobID={inference_job_id}')
    return response.json()

def get_inference_job_image_output(inference_job_id):
    try:
        response = server_request(f'inference/get-inference-job-image-output?jobID={inference_job_id}')
        r = response.json()
        txt2img_inference_job_image_list = []
        for obj in r:
            obj_value = str(obj)
            txt2img_inference_job_image_list.append(obj_value)
        return txt2img_inference_job_image_list
    except Exception as e:
        logger.error(f"An error occurred while getting inference job image output: {e}")
        return []

def get_inference_job_param_output(inference_job_id):
    try:
        response = server_request(f'inference/get-inference-job-param-output?jobID={inference_job_id}')
        r = response.json()
        txt2img_inference_job_param_list = []
        for obj in r:
            obj_value = str(obj)
            txt2img_inference_job_param_list.append(obj_value)
        return txt2img_inference_job_param_list
    except Exception as e:
        logger.error(f"An error occurred while getting inference job param output: {e}")
        return []

def download_images(image_urls: list, local_directory: str):
    if not os.path.exists(local_directory):
        os.makedirs(local_directory)

    image_list = []
    for url in image_urls:
        try:
            response = requests.get(url)
            response.raise_for_status()
            image_name = os.path.basename(url).split('?')[0]
            local_path = os.path.join(local_directory, image_name)

            with open(local_path, 'wb') as f:
                f.write(response.content)
            image_list.append(local_path)
        except requests.exceptions.RequestException as e:
            logger.error(f"Error downloading image {url}: {e}")
    return image_list

def get_model_list_by_type(model_type):
    api_gateway_url = get_variable_from_json('api_gateway_url')
    api_key = get_variable_from_json('api_token')

    # check if api_gateway_url and api_key are set
    if api_gateway_url is None or api_key is None:
        logger.info("api_gateway_url or api_key is not set")
        return []

    # Check if api_url ends with '/', if not append it
    if not api_gateway_url.endswith('/'):
        api_gateway_url += '/'

    url = api_gateway_url + f"checkpoints?status=Active"
    if isinstance(model_type, list):
        url += "&types=" + "&types=".join(model_type)
    else:
        url += f"&types={model_type}"

    try:
        response = requests.get(url=url, headers={'x-api-key': api_key})
        response.raise_for_status()
        json_response = response.json()

        if "checkpoints" not in json_response.keys():
            return []

        checkpoint_list = []
        for ckpt in json_response["checkpoints"]:
            if "name" not in ckpt:
                continue
            if ckpt["name"] is None:
                continue
            if ckpt["type"] is None:
                continue
            ckpt_type = ckpt["type"]
            for ckpt_name in ckpt["name"]:
                ckpt_s3_pos = f"{ckpt['s3Location']}/{ckpt_name}"
                checkpoint_info[ckpt_type][ckpt_name] = ckpt_s3_pos
                checkpoint_list.append(ckpt_name)

        unique_list = list(set(checkpoint_list))
        return unique_list
    except Exception as e:
        logger.error(f"Error fetching model list: {e}")
        return []

def get_checkpoints_by_type(model_type):
    url = "checkpoints?status=Active"
    if isinstance(model_type, list):
        url += "&types=" + "&types=".join(model_type)
    else:
        url += f"&types={model_type}"
    try:
        response = server_request(url)
        response.raise_for_status()
        json_response = response.json()
        if "checkpoints" not in json_response.keys():
            return []
        checkpoint_dict = {}
        for ckpt in json_response["checkpoints"]:
            if "name" not in ckpt:
                continue
            if ckpt["name"] is None:
                continue
            create_time = ckpt['created']
            created = datetime.fromtimestamp(create_time)
            for ckpt_name in ckpt["name"]:
                checkpoint = [ckpt_name, created]
                if ckpt_name not in checkpoint_dict:
                    checkpoint_dict[ckpt_name] = checkpoint
        checkpoint_list = list(checkpoint_dict.values())
        return checkpoint_list
    except Exception as e:
        logging.error(f"Error fetching model list: {e}")
        return []

def update_sd_checkpoints():
    model_type = ["Stable-diffusion"]
    return get_model_list_by_type(model_type)

def get_texual_inversion_list():
    model_type = "embeddings"
    return get_model_list_by_type(model_type)

def get_lora_list():
    model_type = "Lora"
    return get_model_list_by_type(model_type)

def get_hypernetwork_list():
    model_type = "hypernetworks"
    return get_model_list_by_type(model_type)

def get_controlnet_model_list():
    model_type = "ControlNet"
    return get_model_list_by_type(model_type)

def refresh_all_models():
    api_gateway_url = get_variable_from_json('api_gateway_url')
    api_key = get_variable_from_json('api_token')
    try:
        for rp, name in zip(checkpoint_type, checkpoint_name):
            url = api_gateway_url + f"checkpoints?status=Active&types={rp}"
            response = requests.get(url=url, headers={'x-api-key': api_key})
            json_response = response.json()
            logger.debug(f"response url json for model {rp} is {json_response}")
            checkpoint_info[rp] = {}
            if "checkpoints" not in json_response.keys():
                continue
            for ckpt in json_response["checkpoints"]:
                if "name" not in ckpt:
                    continue
                if ckpt["name"] is None:
                    continue
                ckpt_type = ckpt["type"]
                checkpoint_info[ckpt_type] = {}
                for ckpt_name in ckpt["name"]:
                    ckpt_s3_pos = f"{ckpt['s3Location']}/{ckpt_name.split(os.sep)[-1]}"
                    checkpoint_info[ckpt_type][ckpt_name] = ckpt_s3_pos
    except Exception as e:
        logger.error(f"Error refresh all models: {e}")

def sagemaker_upload_model_s3(sd_checkpoints_path, textual_inversion_path, lora_path, hypernetwork_path,
                              controlnet_model_path, vae_path, pr: gradio.Request):
    log = "start upload model to s3:"

    local_paths = [sd_checkpoints_path, textual_inversion_path, lora_path, hypernetwork_path, controlnet_model_path,
                   vae_path]

    logger.info(f"Refresh checkpoints before upload to get rid of duplicate uploads...")
    refresh_all_models()

    for lp, rp in zip(local_paths, checkpoint_type):
        if lp == "" or not lp:
            continue
        logger.debug(f"lp is {lp}")
        model_name = lp.split(os.sep)[-1]

        exist_model_list = list(checkpoint_info[rp].keys())

        if model_name in exist_model_list:
            logger.info(f"!!!skip to upload duplicate model {model_name}")
            continue

        part_size = 1000 * 1024 * 1024
        file_size = os.stat(lp)
        parts_number = math.ceil(file_size.st_size / part_size)
        logger.info(f'!!!!!!!!!!{file_size} {parts_number}')

        # local_tar_path = f'{model_name}.tar'
        local_tar_path = model_name
        payload = {
            "checkpoint_type": rp,
            "filenames": [{
                "filename": local_tar_path,
                "parts_number": parts_number
            }],
            "params": {
                "message": "placeholder for chkpts upload test",
                "creator": pr.username
            }
        }
        api_gateway_url = get_variable_from_json('api_gateway_url')
        # Check if api_url ends with '/', if not append it
        if not api_gateway_url.endswith('/'):
            api_gateway_url += '/'
        api_key = get_variable_from_json('api_token')
        logger.info(f'!!!!!!api_gateway_url {api_gateway_url}')

        url = str(api_gateway_url) + "checkpoint"

        logger.debug(f"Post request for upload s3 presign url: {url}")

        response = requests.post(url=url, json=payload, headers={'x-api-key': api_key})

        try:
            response.raise_for_status()
            json_response = response.json()
            logger.debug(f"Response json {json_response}")
            s3_base = json_response["checkpoint"]["s3_location"]
            checkpoint_id = json_response["checkpoint"]["id"]
            logger.debug(f"Upload to S3 {s3_base}")
            logger.debug(f"Checkpoint ID: {checkpoint_id}")

            s3_signed_urls_resp = json_response["s3PresignUrl"][local_tar_path]
            # Upload src model to S3.
            if rp != "embeddings":
                local_model_path_in_repo = os.sep.join(['models', rp, model_name])
            else:
                local_model_path_in_repo = os.sep.join([rp, model_name])
            logger.debug("Pack the model file.")
            cp(lp, local_model_path_in_repo, recursive=True)
            if rp == "Stable-diffusion":
                model_yaml_name = model_name.split('.')[0] + ".yaml"
                local_model_yaml_path = os.sep.join([*lp.split(os.sep)[:-1], model_yaml_name])
                local_model_yaml_path_in_repo = os.sep.join(["models", rp, model_yaml_name])
                if os.path.isfile(local_model_yaml_path):
                    cp(local_model_yaml_path, local_model_yaml_path_in_repo, recursive=True)
                    tar(mode='c', archive=local_tar_path,
                        sfiles=[local_model_path_in_repo, local_model_yaml_path_in_repo], verbose=True)
                else:
                    tar(mode='c', archive=local_tar_path, sfiles=[local_model_path_in_repo], verbose=True)
            else:
                tar(mode='c', archive=local_tar_path, sfiles=[local_model_path_in_repo], verbose=True)

            multiparts_tags = upload_multipart_files_to_s3_by_signed_url(
                local_tar_path,
                s3_signed_urls_resp,
                part_size
            )

            payload = {
                "checkpoint_id": checkpoint_id,
                "status": "Active",
                "multi_parts_tags": {local_tar_path: multiparts_tags}
            }
            # Start creating model on cloud.
            response = requests.put(url=url, json=payload, headers={'x-api-key': api_key})
            s3_input_path = s3_base
            logger.debug(response)

            log = f"\n finish upload {local_tar_path} to {s3_base}"

            # os.system(f"rm {local_tar_path}")
            rm(local_tar_path, recursive=True)
        except Exception as e:
            logger.error(f"fail to upload model {lp}, error: {e}")

    logger.debug(f"Refresh checkpoints after upload...")
    refresh_all_models()
    return log, None, None, None, None, None, None

def sagemaker_upload_model_s3_local():
    log = "Start upload:"
    return log

def sagemaker_upload_model_s3_url(model_type: str, url_list: str, params: str, pr: gradio.Request):
    model_type = modelTypeMap.get(model_type)
    if not model_type:
        return "Please choose the model type."
    url_pattern = r'(https?|ftp)://[^\s/$.?#].[^\s]*'
    if re.match(f'^{url_pattern}$', url_list):
        url_list = url_list.split(',')
    else:
        return "Please fill in right url list."
    if params:
        params_dict = json.loads(params)
    else:
        params_dict = {}

    params_dict['creator'] = pr.username
    body_params = {'checkpointType': model_type, 'modelUrl': url_list, 'params': params_dict}
    response = server_request_post('upload_checkpoint', body_params)
    response_data = response.json()
    logging.info(f"sagemaker_upload_model_s3_url response:{response_data}")
    log = "uploading……"
    if 'checkpoint' in response_data:
        if response_data['checkpoint'].get('status') == 'Active':
            log = "upload success!"
    return log

def generate_on_cloud(sagemaker_endpoint):
    logger.info(f"checkpiont_info {checkpoint_info}")
    logger.info(f"sagemaker endpoint {sagemaker_endpoint}")
    text = "failed to check endpoint"
    return plaintext_to_html(text)

# create a global event loop and apply the patch to allow nested event loops in single thread
loop = asyncio.get_event_loop()
nest_asyncio.apply()

MAX_RUNNING_LIMIT = 10

def async_loop_wrapper(f):
    global loop
    # check if there are any running or queued tasks inside the event loop
    if loop.is_running():
        # Calculate the number of running tasks
        while len([task for task in asyncio.all_tasks(loop) if not task.done()]) > MAX_RUNNING_LIMIT:
            logger.debug(f'Waiting for {MAX_RUNNING_LIMIT} running tasks to complete')
            time.sleep(1)
    else:
        # check if loop is closed and create a new one
        if loop.is_closed():
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            # log this event since it should never happen
            logger.debug('Event loop was closed, created a new one')

    # Add new task to the event loop
    result = loop.run_until_complete(f())
    return result

def async_loop_wrapper_with_input(sagemaker_endpoint, type):
    global loop
    # check if there are any running or queued tasks inside the event loop
    if loop.is_running():
        # Calculate the number of running tasks
        while len([task for task in asyncio.all_tasks(loop) if not task.done()]) > MAX_RUNNING_LIMIT:
            logger.debug(f'Waiting for {MAX_RUNNING_LIMIT} running tasks to complete')
            time.sleep(1)
    else:
        # check if loop is closed and create a new one
        if loop.is_closed():
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            # log this event since it should never happen
            logger.debug('Event loop was closed, created a new one')

    # Add new task to the event loop
    result = loop.run_until_complete(call_remote_inference(sagemaker_endpoint, type))
    return result

def call_interrogate_clip(sagemaker_endpoint, init_img, sketch, init_img_with_mask, inpaint_color_sketch,
                          init_img_inpaint, init_mask_inpaint):
    return async_loop_wrapper_with_input(sagemaker_endpoint, 'interrogate_clip')

def call_interrogate_deepbooru(sagemaker_endpoint, init_img, sketch, init_img_with_mask, inpaint_color_sketch,
                               init_img_inpaint, init_mask_inpaint):
    return async_loop_wrapper_with_input(sagemaker_endpoint, 'interrogate_deepbooru')

async def call_remote_inference(sagemaker_endpoint, type):
    logger.debug(f"chosen ep {sagemaker_endpoint}")
    logger.debug(f"inference type is {type}")

    if sagemaker_endpoint == '':
        image_list = []  # Return an empty list if selected_value is None
        info_text = ''
        infotexts = "Failed! Please choose the endpoint in 'InService' states "
        return image_list, info_text, plaintext_to_html(infotexts)
    elif sagemaker_endpoint == 'FAILURE':
        image_list = []  # Return an empty list if selected_value is None
        info_text = ''
        infotexts = "Failed upload the config to cloud  "
        return image_list, info_text, plaintext_to_html(infotexts)

    sagemaker_endpoint_status = sagemaker_endpoint.split("+")[1]

    if sagemaker_endpoint_status != "InService":
        image_list = []  # Return an empty list if selected_value is None
        info_text = ''
        infotexts = "Failed! Please choose the endpoint in 'InService' states "
        return image_list, info_text, plaintext_to_html(infotexts)

    api_gateway_url = get_variable_from_json('api_gateway_url')
    # Check if api_url ends with '/', if not append it
    if not api_gateway_url.endswith('/'):
        api_gateway_url += '/'
    api_key = get_variable_from_json('api_token')

    # stage 2: inference using endpoint_name
    headers = {
        "x-api-key": api_key,
        "Content-Type": "application/json"
    }
    checkpoint_info['sagemaker_endpoint'] = sagemaker_endpoint.split("+")[0]
    payload = checkpoint_info
    payload['task_type'] = type
    logger.info(f"checkpointinfo is {payload}")

    inference_url = f"{api_gateway_url}inference/run-sagemaker-inference"
    response = requests.post(inference_url, json=payload, headers=headers)
    logger.info(f"Raw server response: {response.text}")
    try:
        r = response.json()
    except JSONDecodeError as e:
        logger.error(f"Failed to decode JSON response: {e}")
        logger.error(f"Raw server response: {response.text}")
    else:
        inference_id = r.get('inference_id')  # Assuming the response contains 'inference_id' field
        try:
            return process_result_by_inference_id(inference_id)
        except Exception as e:
            logger.error(f"Failed to get inference job {inference_id}, error: {e}")

def process_result_by_inference_id(inference_id):
    image_list = []  # Return an empty list if selected_value is None
    info_text = ''
    infotexts = f"Inference id is {inference_id}, please check all historical inference result in 'Inference Job' dropdown list"
    json_list = []
    prompt_txt = ''

    resp = get_inference_job(inference_id)
    if resp is None:
        return image_list, info_text, plaintext_to_html(infotexts)
    else:
        if resp['taskType'] in ['txt2img', 'img2img', 'interrogate_clip', 'interrogate_deepbooru']:
            while resp['status'] == "inprogress":
                time.sleep(3)
                resp = get_inference_job(inference_id)
            if resp['status'] == "failed":
                infotexts = f"Inference job {inference_id} is failed, error message: {resp['sagemakerRaw']}"
                return image_list, info_text, plaintext_to_html(infotexts), infotexts
            elif resp['status'] == "succeed":
                if resp['taskType'] in ['interrogate_clip', 'interrogate_deepbooru']:
                    prompt_txt = resp['caption']
                    # return with default value, including image_list, info_text, infotexts
                    return image_list, info_text, plaintext_to_html(infotexts), prompt_txt
                images = get_inference_job_image_output(inference_id.strip())
                inference_param_json_list = get_inference_job_param_output(inference_id)
                # todo: these not need anymore
                if resp['taskType'] == "txt2img":
                    image_list = download_images(images, f"outputs/txt2img-images/{get_current_date()}/{inference_id}/")
                    json_list = download_images(inference_param_json_list,
                                                f"outputs/txt2img-images/{get_current_date()}/{inference_id}/")
                    json_file = f"outputs/txt2img-images/{get_current_date()}/{inference_id}/{inference_id}_param.json"
                elif resp['taskType'] == "img2img":
                    image_list = download_images(images, f"outputs/img2img-images/{get_current_date()}/{inference_id}/")
                    json_list = download_images(inference_param_json_list,
                                                f"outputs/img2img-images/{get_current_date()}/{inference_id}/")
                    json_file = f"outputs/img2img-images/{get_current_date()}/{inference_id}/{inference_id}_param.json"
                if os.path.isfile(json_file):
                    with open(json_file) as f:
                        log_file = json.load(f)
                        info_text = log_file["info"]
                        infotexts = f"Inference id is {inference_id}\n" + json.loads(info_text)["infotexts"][0]
                else:
                    logger.debug(f"File {json_file} does not exist.")
                    info_text = 'something wrong when trying to download the inference parameters'
                    infotexts = info_text
                return image_list, info_text, plaintext_to_html(infotexts), infotexts
        else:
            return image_list, info_text, plaintext_to_html(infotexts), infotexts

def modelmerger_on_cloud_func(primary_model_name, secondary_model_name, teritary_model_name):
    logger.debug(f"function under development, current checkpoint_info is {checkpoint_info}")
    api_gateway_url = get_variable_from_json('api_gateway_url')
    # Check if api_url ends with '/', if not append it
    if not api_gateway_url.endswith('/'):
        api_gateway_url += '/'
    api_key = get_variable_from_json('api_token')

    if api_gateway_url is None:
        logger.debug(f"modelmerger: failed to get the api-gateway url, can not fetch remote data")
        return []
    modelmerge_url = f"{api_gateway_url}inference/run-model-merge"

    payload = {
        "primary_model_name": primary_model_name,
        "secondary_model_name": secondary_model_name,
        "tertiary_model_name": teritary_model_name
    }

    headers = {
        "x-api-key": api_key,
        "Content-Type": "application/json"
    }

    response = requests.post(modelmerge_url, json=payload, headers=headers)

    try:
        r = response.json()
    except JSONDecodeError as e:
        logger.error(f"Failed to decode JSON response: {e}")
        logger.error(f"Raw server response: {response.text}")
    else:
        logger.debug(f"response for rest api {r}")

# def txt2img_config_save():
#     # placeholder for saving txt2img config
#     pass

def displayEndpointInfo(input_string: str):
    logger.debug(f"selected value is {input_string}")
    if not input_string:
        return
    parts = input_string.split('+')

    if len(parts) < 2:
        return plaintext_to_html("")

    endpoint_job_id, status = parts[0], parts[1]

    if status == 'failed':
        response = server_request(f'inference/get-endpoint-deployment-job?jobID={endpoint_job_id}')
        # Do something with the response
        r = response.json()
        if "error" in r:
            return plaintext_to_html(r["error"])
        else:
            return plaintext_to_html(r["EndpointDeploymentJobId"])
    else:
        return plaintext_to_html("")

def update_txt2imgPrompt_from_TextualInversion(selected_items, txt2img_prompt):
    return update_txt2imgPrompt_from_model_select(selected_items, txt2img_prompt, 'embeddings', False)

def update_txt2imgPrompt_from_Hypernetworks(selected_items, txt2img_prompt):
    return update_txt2imgPrompt_from_model_select(selected_items, txt2img_prompt, 'hypernetworks', True)

def update_txt2imgPrompt_from_Lora(selected_items, txt2img_prompt):
    return update_txt2imgPrompt_from_model_select(selected_items, txt2img_prompt, 'Lora', True)

def update_txt2imgPrompt_from_model_select(selected_items, txt2img_prompt, model_name='embeddings',
                                           with_angle_brackets=False):
    logger.debug(selected_items)  # example ['FastNegativeV2.pt']
    logger.debug(txt2img_prompt)
    logger.debug(get_model_list_by_type('embeddings'))
    full_dropdown_items = get_model_list_by_type(model_name)  # example ['FastNegativeV2.pt', 'okuryl3nko.pt']

    # Remove extensions from selected_items and full_dropdown_items
    selected_items = [item.split('.')[0] for item in selected_items]
    full_dropdown_items = [item.split('.')[0] for item in full_dropdown_items]

    # Loop over each item in full_dropdown_items and remove it from txt2img_prompt
    type_str = ''
    if model_name == 'Lora':
        type_str = 'lora:'
    elif model_name == 'hypernetworks':
        type_str = 'hypernet:'
    for item in full_dropdown_items:
        if with_angle_brackets:
            txt2img_prompt = re.sub(f'<{type_str}{item}:\d+>', "", txt2img_prompt).strip()
        else:
            txt2img_prompt = txt2img_prompt.replace(item, "").strip()

    # Loop over each item in selected_items and append it to txt2img_prompt
    for item in selected_items:
        if with_angle_brackets:
            txt2img_prompt += ' ' + '<' + type_str + item + ':1>'
        else:
            txt2img_prompt += ' ' + item

    # Remove any leading or trailing whitespace
    txt2img_prompt = txt2img_prompt.strip()

    return txt2img_prompt

def fake_gan(selected_value, original_prompt):
    logger.debug(f"selected value is {selected_value}")
    logger.debug(f"original prompt is {original_prompt}")
    if selected_value is not None:
        delimiter = "-->"
        parts = selected_value.split(delimiter)
        # Extract the InferenceJobId value
        inference_job_id = parts[3].strip()
        inference_job_status = parts[2].strip()
        inference_job_taskType = parts[1].strip()
        if inference_job_status == 'inprogress':
            return [], [], plaintext_to_html('inference still in progress')

        if inference_job_taskType in ["txt2img", "img2img"]:
            prompt_txt = original_prompt
            images = get_inference_job_image_output(inference_job_id)
            image_list = []
            json_list = []
            inference_pram_json_list = get_inference_job_param_output(inference_job_id)
            # output directory mapping to task type
            if inference_job_taskType == "txt2img":
                image_list = download_images(images, f"outputs/txt2img-images/{get_current_date()}/{inference_job_id}/")
                json_list = download_images(inference_pram_json_list,
                                            f"outputs/txt2img-images/{get_current_date()}/{inference_job_id}/")
                json_file = f"outputs/txt2img-images/{get_current_date()}/{inference_job_id}/{inference_job_id}_param.json"
            elif inference_job_taskType == "img2img":
                image_list = download_images(images, f"outputs/img2img-images/{get_current_date()}/{inference_job_id}/")
                json_list = download_images(inference_pram_json_list,
                                            f"outputs/img2img-images/{get_current_date()}/{inference_job_id}/")
                json_file = f"outputs/img2img-images/{get_current_date()}/{inference_job_id}/{inference_job_id}_param.json"
            logger.debug(f"{str(images)}")
            logger.debug(f"{str(inference_pram_json_list)}")
            if os.path.isfile(json_file):
                with open(json_file) as f:
                    log_file = json.load(f)
                    info_text = log_file["info"]
                    infotexts = json.loads(info_text)["infotexts"][0]
            else:
                logger.debug(f"File {json_file} does not exist.")
                info_text = 'something wrong when trying to download the inference parameters'
                infotexts = 'something wrong when trying to download the inference parameters'
        elif inference_job_taskType in ["interrogate_clip", "interrogate_deepbooru"]:
            job_status = get_inference_job(inference_job_id)
            logger.debug(job_status)
            caption = job_status['caption']
            prompt_txt = caption
            image_list = []  # Return an empty list if selected_value is None
            json_list = []
            info_text = ''
            infotexts = ''
    else:
        prompt_txt = original_prompt
        image_list = []  # Return an empty list if selected_value is None
        json_list = []
        info_text = ''
        infotexts = ''
    return image_list, info_text, plaintext_to_html(infotexts), prompt_txt

def display_inference_result(inference_id: str):
    logger.debug(f"selected value is {inference_id}")
    if inference_id is not None:
        # Extract the InferenceJobId value
        inference_job_id = inference_id
        images = get_inference_job_image_output(inference_job_id)
        image_list = []
        image_list = download_images(images, f"outputs/txt2img-images/{get_current_date()}/{inference_job_id}/")

        inference_pram_json_list = get_inference_job_param_output(inference_job_id)
        json_list = []
        json_list = download_images(inference_pram_json_list,
                                    f"outputs/txt2img-images/{get_current_date()}/{inference_job_id}/")

        logger.debug(f"{str(images)}")
        logger.debug(f"{str(inference_pram_json_list)}")

        json_file = f"outputs/txt2img-images/{get_current_date()}/{inference_job_id}/{inference_job_id}_param.json"

        f = open(json_file)

        log_file = json.load(f)

        info_text = log_file["info"]

        infotexts = json.loads(info_text)["infotexts"][0]
    else:
        image_list = []  # Return an empty list if selected_value is None
        json_list = []
        info_text = ''

    return image_list, info_text, plaintext_to_html(infotexts)

def init_refresh_resource_list_from_cloud():
    logger.debug(f"start refreshing resource list from cloud")
    if get_variable_from_json('api_gateway_url') is not None:
        if not cloud_auth_manager.enableAuth:
            # api_manager.list_all_sagemaker_endpoints()
            refresh_all_models()
            get_texual_inversion_list()
            get_lora_list()
            get_hypernetwork_list()
            get_controlnet_model_list()
            # get_inference_job_list()
        else:
            logger.debug('auth enabled, not preload load any model')
    else:
        logger.debug(f"there is no api-gateway url and token in local file,")

def on_txt_time_change(start_time, end_time):
    logger.debug(f"!!!!!!!!!on_txt_time_change!!!!!!{start_time},{end_time}")
    global start_time_picker_txt_value
    global end_time_picker_txt_value
    start_time_picker_txt_value = start_time
    end_time_picker_txt_value = end_time
    return query_inference_job_list(txt_task_type, txt_status, txt_endpoint, txt_checkpoint, "txt2img")

def on_img_time_change(start_time, end_time):
    logger.debug(f"!!!!!!!!!on_img_time_change!!!!!!{start_time},{end_time}")
    global start_time_picker_img_value
    global end_time_picker_img_value
    start_time_picker_img_value = start_time
    end_time_picker_img_value = end_time
    return query_inference_job_list(img_task_type, img_status, img_endpoint, img_checkpoint, "img2img")

def load_inference_job_list(username, usertoken):
    inference_jobs = [None_Option_For_On_Cloud_Model]
    inferences_jobs_list = api_manager.list_all_inference_jobs_on_cloud(username, usertoken)

    temp_list = []
    for obj in inferences_jobs_list:
        if obj.get('completeTime') is None:
            complete_time = obj.get('startTime')
        else:
            complete_time = obj.get('completeTime')
        status = obj.get('status')
        task_type = obj.get('taskType', 'txt2img')
        inference_job_id = obj.get('InferenceJobId')
        # if filter_checkbox and task_type not in selected_types:
        #     continue
        temp_list.append((complete_time, f"{complete_time}-->{task_type}-->{status}-->{inference_job_id}"))
    # Sort the list based on completeTime in ascending order
    sorted_list = sorted(temp_list, key=lambda x: x[0], reverse=False)
    # Append the sorted combined strings to the txt2img_inference_job_ids list
    for item in sorted_list:
        inference_jobs.append(item[1])

    return inference_jobs

def load_model_list(username, user_token):
    models_on_cloud = [None_Option_For_On_Cloud_Model]
    models_on_cloud += list(set([model['name'] for model in api_manager.list_models_on_cloud(username, user_token)]))
    return models_on_cloud

def load_lora_models(username, user_token):
    return list(set([model['name'] for model in api_manager.list_models_on_cloud(username, user_token, types='Lora')]))

def load_hypernetworks_models(username, user_token):
    return list(set([model['name'] for model in api_manager.list_models_on_cloud(username, user_token, types='hypernetworks')]))

def load_vae_list(username, user_token):
    vae_model_on_cloud = ['Automatic', 'None']
    vae_model_on_cloud += list(set([model['name'] for model in api_manager.list_models_on_cloud(username, user_token, types='VAE')]))
    return vae_model_on_cloud

def load_controlnet_list(username, user_token):
    vae_model_on_cloud = ['None']
    vae_model_on_cloud += list(set([model['name'] for model in api_manager.list_models_on_cloud(username, user_token, types='ControlNet')]))
    return vae_model_on_cloud

def load_embeddings_list(username, user_token):
    # vae_model_on_cloud = ['None']
    vae_model_on_cloud = list(set([model['name'] for model in api_manager.list_models_on_cloud(username, user_token, types='embeddings')]))
    return vae_model_on_cloud

def create_ui(is_img2img):
    global txt2img_gallery, txt2img_generation_info
    import modules.ui

    init_refresh_resource_list_from_cloud()

    with gr.Blocks() as sagemaker_inference_tab:
        gr.HTML('
Amazon SageMaker Inference
')
        sagemaker_html_log = gr.HTML(elem_id=f'html_log_sagemaker')
        with gr.Column():
            with gr.Row():
                lora_and_hypernet_models_state = gr.State({})
                sd_model_on_cloud_dropdown = gr.Dropdown(choices=[], value=None_Option_For_On_Cloud_Model,
                                                         label='Stable Diffusion Checkpoint Used on Cloud')

                create_refresh_button_by_user(sd_model_on_cloud_dropdown,
                                              lambda *args: None,
                                              lambda username: {
                                                  'choices': load_model_list(username, username)
                                              }, 'refresh_cloud_model_down')

            with gr.Row():
                sd_vae_on_cloud_dropdown = gr.Dropdown(choices=[], value='Automatic',
                                                       label='SD Vae on Cloud')

                create_refresh_button_by_user(sd_vae_on_cloud_dropdown,
                                              lambda *args: None,
                                              lambda username: {
                                                  'choices': load_vae_list(username, username)
                                              }, 'refresh_cloud_vae_down')
            with gr.Row(visible=is_img2img):
                gr.HTML('
')

            with gr.Row(visible=is_img2img):
                global generate_on_cloud_button_with_js
                # if not is_img2img:
                #     generate_on_cloud_button_with_js = gr.Button(value="Generate on Cloud", variant='primary', elem_id="generate_on_cloud_with_cloud_config_button",queue=True, show_progress=True)
                global generate_on_cloud_button_with_js_img2img
                global interrogate_clip_on_cloud_button
                global interrogate_deep_booru_on_cloud_button

                interrogate_clip_on_cloud_button = gr.Button(value="Interrogate CLIP",  variant='primary',
                                                             elem_id="interrogate_clip_on_cloud_button")
                interrogate_deep_booru_on_cloud_button = gr.Button(value="Interrogte DeepBooru",  variant='primary',
                                                                   elem_id="interrogate_deep_booru_on_cloud_button")
            with gr.Row():
                gr.HTML('
')

            with gr.Row():
                global inference_job_dropdown
                # global txt2img_inference_job_ids

                inference_job_dropdown = gr.Dropdown(choices=[], value=None_Option_For_On_Cloud_Model,
                                                     label="Inference Job: Time-Type-Status-Uuid")
                create_refresh_button_by_user(inference_job_dropdown,
                                              lambda *args: None,
                                              lambda username: {
                                                  'choices': load_inference_job_list(username, username)
                                              }, 'refresh_inference_job_down')
                # inference_job_dropdown = gr.Dropdown(choices=txt2img_inference_job_ids,
                #                                      label="Inference Job: Time-Type-Status-Uuid",
                #                                      elem_id="txt2img_inference_job_ids_dropdown"
                #                                      )
                # txt2img_inference_job_ids_refresh_button = create_refresh_button(inference_job_dropdown,
                #                                                                  query_inference_job_list,
                #                                                                  lambda: {
                #                                                                     "choices": txt2img_inference_job_ids,
                #                                                                     "value": None},
                #                                                                  "refresh_txt2img_inference_job_ids")
            # fixme: inference filters need to be fixed
            # with gr.Row():
            #     inference_job_filter = gr.Checkbox(
            #         label="Advanced Inference Job filter", value=False, visible=True
            #     )
            #     inference_job_page = gr.Checkbox(label="Show All(unchecked: max 10 items)",
            #                                      elem_id="inference_job_page_checkbox", value=False)
            # with gr.Row(variant='panel', visible=False) as filter_row:
            #     with gr.Column(scale=1):
            #         gr.HTML(value="Inference Job type filters")
            #     with gr.Column(scale=2):
            #         with gr.Row():
            #             task_type_choices = ["txt2img", "img2img", "interrogate_clip", "interrogate_deepbooru"]
            #             task_type_dropdown = gr.Dropdown(label="Task Type", choices=task_type_choices,
            #                                              elem_id="task_type_ids_dropdown")
            #             status_choices = ["succeed", "inprogress", "failed"]
            #             status_dropdown = gr.Dropdown(label="Status", choices=status_choices,
            #                                           elem_id="task_status_dropdown")
            #         # with gr.Row():
            #         #     sagemaker_endpoint_filter = gr.Dropdown(api_manager.list_all_sagemaker_endpoints(),
            #         #                                             label="SageMaker Endpoint",
            #         #                                             elem_id="sagemaker_endpoint_dropdown")
            #         #     modules.ui.create_refresh_button(sagemaker_endpoint_filter, lambda: None,
            #         #                                      lambda: {"choices": api_manager.list_all_sagemaker_endpoints()},
            #         #                                      "refresh_sagemaker_endpoints")
            #
            #         with gr.Row():
            #             sd_checkpoint_filter = gr.Dropdown(label="Checkpoint", choices=sorted(update_sd_checkpoints()),
            #                                                elem_id="stable_diffusion_checkpoint_dropdown")
            #             modules.ui.create_refresh_button(sd_checkpoint_filter, update_sd_checkpoints,
            #                                              lambda: {"choices": sorted(update_sd_checkpoints())},
            #                                              "refresh_sd_checkpoints")
            #         if is_img2img:
            #             with gr.Row():
            #                 start_time_picker_img = gr.HTML(elem_id="start_timepicker_img_e",
            #                                                 value="""
            #
            #                                                     Start Time
            #                                                     <input type="date"
            #                                                            lang="en"
            #                                                            id="start_timepicker_img"
            #                                                            min="2023-01-01"
            #                                                            max="2033-12-31"
            #                                                            class="wrap svelte-aqlk7e"
            #                                                            style="color: #6B7280"
            #                                                            onchange="inference_job_timepicker_img_change()" />
            #
            #                                                 """)
            #                 end_time_picker_img = gr.HTML(elem_id="end_timepicker_img_e",
            #                                               value="""
            #
            #                                                 End Time
            #                                                 <input type="date"
            #                                                        lang="en"
            #                                                        id="end_timepicker_img"
            #                                                        min="2023-01-01" max="2033-12-31"
            #                                                        class="wrap svelte-aqlk7e"
            #                                                        style="color: #6B7280"
            #                                                        onchange="inference_job_timepicker_img_change()">
            #
            #                                               """)
            #                 start_time_picker_img_hidden = gr.Button(elem_id="start_time_picker_img_hidden",
            #                                                          visible=True)
            #                 end_time_picker_img_hidden = gr.Button(elem_id="end_time_picker_img_hidden",
            #                                                        visible=True)
            #             start_time_picker_img_hidden.click(fn=on_img_time_change,
            #                                                _js='get_time_img_value',
            #                                                inputs=[start_time_picker_img, end_time_picker_img],
            #                                                outputs=inference_job_dropdown)
            #             end_time_picker_img_hidden.click(fn=on_img_time_change,
            #                                              _js='get_time_img_value',
            #                                              inputs=[start_time_picker_img, end_time_picker_img],
            #                                              outputs=inference_job_dropdown
            #                                              )
            #             task_type_dropdown.change(fn=query_img_inference_job_list,
            #                                       inputs=[task_type_dropdown, status_dropdown,
            #                                               sagemaker_endpoint_filter,
            #                                               sd_checkpoint_filter], outputs=inference_job_dropdown)
            #             status_dropdown.change(fn=query_img_inference_job_list,
            #                                    inputs=[task_type_dropdown, status_dropdown, sagemaker_endpoint_filter,
            #                                            sd_checkpoint_filter], outputs=inference_job_dropdown)
            #
            #             sagemaker_endpoint_filter.change(fn=query_img_inference_job_list,
            #                                              inputs=[task_type_dropdown, status_dropdown,
            #                                                      sagemaker_endpoint_filter,
            #                                                      sd_checkpoint_filter], outputs=inference_job_dropdown)
            #
            #             sd_checkpoint_filter.change(fn=query_img_inference_job_list,
            #                                         inputs=[task_type_dropdown, status_dropdown,
            #                                                 sagemaker_endpoint_filter,
            #                                                 sd_checkpoint_filter], outputs=inference_job_dropdown)
            #         else:
            #             with gr.Row():
            #                 start_time_picker_text = gr.HTML(elem_id="start_timepicker_text_e",
            #                                                  value="""
            #
            #                                                     Start Time
            #                                                     <input type="date" lang="en" id="start_timepicker_text"
            #                                                            min="2023-01-01" max="2033-12-31"
            #                                                            class="wrap svelte-aqlk7e" style="color: #6B7280"
            #                                                            onchange="inference_job_timepicker_text_change()">
            #
            #                                                  """)
            #                 end_time_picker_text = gr.HTML(elem_id="end_timepicker_text_e",
            #                                                value="""
            #
            #                                                     End Time
            #                                                     <input type="date" lang="en" id="end_timepicker_text"
            #                                                             min="2023-01-01" max="2033-12-31"
            #                                                             class="wrap svelte-aqlk7e"
            #                                                             style="color: #6B7280"
            #                                                             onchange="inference_job_timepicker_text_change()">
            #
            #                                                """)
            #                 start_time_picker_button_hidden = gr.Button(elem_id="start_time_picker_button_hidden",
            #                                                             visible=False)
            #                 end_time_picker_button_hidden = gr.Button(elem_id="end_time_picker_button_hidden",
            #                                                           visible=False)
            #             start_time_picker_button_hidden.click(fn=on_txt_time_change,
            #                                                   _js='get_time_button_value',
            #                                                   inputs=[start_time_picker_text, end_time_picker_text],
            #                                                   outputs=inference_job_dropdown)
            #             end_time_picker_button_hidden.click(fn=on_txt_time_change,
            #                                                 _js='get_time_button_value',
            #                                                 inputs=[start_time_picker_text, end_time_picker_text],
            #                                                 outputs=inference_job_dropdown)
            #             task_type_dropdown.change(fn=query_txt_inference_job_list,
            #                                       inputs=[task_type_dropdown, status_dropdown,
            #                                               sagemaker_endpoint_filter, sd_checkpoint_filter],
            #                                       outputs=inference_job_dropdown)
            #             status_dropdown.change(fn=query_txt_inference_job_list,
            #                                    inputs=[task_type_dropdown, status_dropdown,
            #                                            sagemaker_endpoint_filter,
            #                                            sd_checkpoint_filter], outputs=inference_job_dropdown)
            #             sagemaker_endpoint_filter.change(fn=query_txt_inference_job_list,
            #                                              inputs=[task_type_dropdown, status_dropdown,
            #                                                      sagemaker_endpoint_filter,
            #                                                      sd_checkpoint_filter], outputs=inference_job_dropdown)
            #             sd_checkpoint_filter.change(fn=query_txt_inference_job_list,
            #                                         inputs=[task_type_dropdown, status_dropdown,
            #                                                 sagemaker_endpoint_filter, sd_checkpoint_filter],
            #                                         outputs=inference_job_dropdown)
            #
            #         def toggle_new_rows(create_from):
            #             global start_time_picker_txt_value
            #             start_time_picker_txt_value = None
            #             global end_time_picker_txt_value
            #             end_time_picker_txt_value = None
            #             return [gr.update(visible=create_from), None, None, None, None]
            #
            #         inference_job_filter.change(
            #             fn=toggle_new_rows,
            #             inputs=[inference_job_filter],
            #             outputs=[filter_row, task_type_dropdown, status_dropdown, sagemaker_endpoint_filter,
            #                      sd_checkpoint_filter],
            #         )
            #         hidden_check_type = gr.Textbox(elem_id="hidden_check_type", value=is_img2img, visible=False)
            #         inference_job_page.change(fn=query_page_inference_job_list,
            #                                   inputs=[task_type_dropdown, status_dropdown,
            #                                           sagemaker_endpoint_filter,
            #                                           sd_checkpoint_filter, hidden_check_type,
            #                                           inference_job_page],
            #
            #                                   outputs=inference_job_dropdown)

                def setup_inference_for_plugin(pr: gr.Request):
                    models_on_cloud = load_model_list(pr.username, pr.username)
                    vae_model_on_cloud = load_vae_list(pr.username, pr.username)
                    inference_jobs = load_inference_job_list(pr.username, pr.username)
                    lora_models_on_cloud = load_lora_models(username=pr.username, user_token=pr.username)
                    hypernetworks_models_on_cloud = load_hypernetworks_models(pr.username, pr.username)
                    controlnet_list = load_controlnet_list(pr.username, pr.username)
                    lora_hypernets = {
                        'lora': lora_models_on_cloud,
                        'hypernet': hypernetworks_models_on_cloud,
                        'controlnet': controlnet_list,
                    }

                    return lora_hypernets, \
                        gr.update(choices=models_on_cloud), \
                        gr.update(choices=inference_jobs), \
                        gr.update(choices=vae_model_on_cloud)

                sagemaker_inference_tab.load(fn=setup_inference_for_plugin, inputs=[],
                                             outputs=[
                                                 lora_and_hypernet_models_state,
                                                 sd_model_on_cloud_dropdown,
                                                 inference_job_dropdown,
                                                 sd_vae_on_cloud_dropdown]
                                             )
    with gr.Group():
        with gr.Accordion("Open for Checkpoint Merge in the Cloud!", visible=False, open=False):
            sagemaker_html_log = gr.HTML(elem_id=f'html_log_sagemaker')
            with FormRow(elem_id="modelmerger_models_in_the_cloud"):
                global primary_model_name
                primary_model_name = gr.Dropdown(choices=sorted(update_sd_checkpoints()),
                                                 elem_id="modelmerger_primary_model_name_in_the_cloud",
                                                 label="Primary model (A) in the cloud")
                create_refresh_button(primary_model_name, update_sd_checkpoints,
                                      lambda: {"choices": sorted(update_sd_checkpoints())},
                                      "refresh_checkpoint_A_in_the_cloud")

                global secondary_model_name
                secondary_model_name = gr.Dropdown(choices=sorted(update_sd_checkpoints()),
                                                   elem_id="modelmerger_secondary_model_name_in_the_cloud",
                                                   label="Secondary model (B) in the cloud")
                create_refresh_button(secondary_model_name, update_sd_checkpoints,
                                      lambda: {"choices": sorted(update_sd_checkpoints())},
                                      "refresh_checkpoint_B_in_the_cloud")

                global tertiary_model_name
                tertiary_model_name = gr.Dropdown(choices=sorted(update_sd_checkpoints()),
                                                  elem_id="modelmerger_tertiary_model_name_in_the_cloud",
                                                  label="Tertiary model (C) in the cloud")
                create_refresh_button(tertiary_model_name, update_sd_checkpoints,
                                      lambda: {"choices": sorted(update_sd_checkpoints())},
                                      "refresh_checkpoint_C_in_the_cloud")
            with gr.Row():
                global modelmerger_merge_on_cloud
                modelmerger_merge_on_cloud = gr.Button(elem_id="modelmerger_merge_in_the_cloud", value="Merge on Cloud",
                                                       variant='primary')

    return sd_model_on_cloud_dropdown, sd_vae_on_cloud_dropdown, inference_job_dropdown, primary_model_name, secondary_model_name, tertiary_model_name, modelmerger_merge_on_cloud, lora_and_hypernet_models_state


# 프로그래머스 LV1 - 완주하지 못한 선수(Counter 활용)
# https://programmers.co.kr/learn/courses/30/lessons/42576?language=python3
import collections

def solution(participant, completion):
    answer = '' # 리턴할 값 answer

    '''
    participant와 completion 길이의 차는 1이다.
    이를 활용하기 위해 Counter 클래스를 활용하면 된다.
    participant와 completion 배열 간의 차를 구하고
    마지막 Counter에서 Key 값을 읽어오기 위해 list(value.keys())[0]를 answer에 대입한다.
    '''
    value = collections.Counter(participant) - collections.Counter(completion)

    answer = list(value.keys())[0]

    return answer

participant = ["mislav", "stanko", "mislav", "ana"]
completion = 	["stanko", "ana", "mislav"]
print(solution(participant, completion))


import gdal
import os
import sys
import cv2
import numpy as np
from PIL import Image
from matplotlib import pyplot as plt
from functools import reduce

from MoreOne import Ui_Dialog
from PyQt5.QtWidgets import QDialog, QFileDialog,QApplication
from base_functions import drawMatchesKnn_cv2, save_matchedpoints_in_file

import sys

class myWindow(QDialog, Ui_Dialog):
    def __init__(self):
        super(myWindow,self).__init__()
        self.setupUi(self)

    def sopen1(self):
        fileName, filetype = QFileDialog.getOpenFileName(self,
                                    "选取文件",
                                    "/home/scrc/",
                                    "image Files (*.tif);;All Files (*)")
        self.lineEdit_one.setText(fileName)

    def sopen2(self):
        fileName, filetype = QFileDialog.getOpenFileName(self,
                                                         "选取文件",
                                                         "/home/scrc/",
                                                         "image Files (*.tif);;All Files (*)")
        self.lineEdit_two.setText(fileName)

    def sok(self):
        filename_first=self.lineEdit_one.text()
        filename_second = self.lineEdit_two.text()
        root = os.path.split(filename_first)[0]

        temp = list(filter(str.isdigit, os.path.split(filename_first)[1]))
        s_1 = reduce(lambda x, y:str(x)+str(y), temp)
        temp = list(filter(str.isdigit, os.path.split(filename_second)[1]))
        s_2 = reduce(lambda x, y: str(x)+str(y), temp)
        #    print ("{}_{}".format(s_1,s_2))
        # textfile = "{}_{}.txt".format(s_1, s_2)

        dataset = gdal.Open(filename_first)
        if dataset == None:
            print(filename_first + '文件无法打开')
            sys.exit(1)
        im_width = dataset.RasterXSize
        im_height = dataset.RasterYSize
        im_bands = dataset.RasterCount

        if not 1 == im_bands:
            print("image bands > 1")
            sys.exit(0)

        im_data = dataset.ReadAsArray(0, 0, im_width, im_height)
        del dataset

        img_1 = im_data.astype(np.uint8)
        img_ss = np.zeros((im_height, im_width, 3), dtype=np.uint8)
        for i in range(3):
            img_ss[:, :, i] = img_1

        dataset_2 = gdal.Open(filename_second)
        if dataset_2 == None:
            print(filename_second + '文件无法打开')
            sys.exit(1)
        im_width_2 = dataset_2.RasterXSize
        im_height_2 = dataset_2.RasterYSize
        im_data_2 = dataset_2.ReadAsArray(0, 0, im_width_2, im_height_2)
        del dataset_2

        img_2 = im_data_2.astype(np.uint8)
        img_sp = np.zeros((im_height_2, im_width_2, 3), dtype=np.uint8)
        for i in range(3):
            img_sp[:, :, i] = img_2

        """
        采用sift算子，提取匹配点，并存放到TXT文件中
        """
        # sift = cv2.xfeatures2d.SIFT_create()
        orb = cv2.ORB_create(5000)
        kp1, des1 = orb.detectAndCompute(img_ss, None)
        kp2, des2 = orb.detectAndCompute(img_sp, None)
        bf = cv2.BFMatcher(cv2.NORM_HAMMING)
        # bf = cv2.BFMatcher()
        matches = bf.knnMatch(des1, trainDescriptors=des2, k=2)

        goodMatch = []
        for m, n in matches:
            if m.distance < 0.75 * n.distance:
                goodMatch.append(m)

        num_matched_point = len(goodMatch)
        print("匹配的点有{}个".format(num_matched_point))
        if num_matched_point < 2:
            print("match point less than 2")
            # continue

        imgfile = "{}_{}.png".format(s_1, s_2)
        out_img_file = os.path.join(root, imgfile)
        drawMatchesKnn_cv2(img_ss, kp1, img_sp, kp2, goodMatch, out_img_file)

        textfile = "{}_{}.txt".format(s_1, s_2)
        out_txt_file = os.path.join(root, textfile)
        save_matchedpoints_in_file(im_data, kp1, im_data_2, kp2, goodMatch, out_txt_file)

if __name__=='__main__':
    app = QApplication(sys.argv)
    window = myWindow()
    window.show()
    sys.exit(app.exec_())


#!/usr/bin/env python3

N = int(input())
Timer = [0] + list(map(int, input().split()))

all = sum(Timer)
dp = []
for i in range(N+1):
    dp.append([False] * (all+1))

dp[0][0] = True

for i in range(1, N+1):
    for j in range(all+1):
        if dp[i-1][j]:
            dp[i][j] = True
        if j-Timer[i] >= 0:
            if dp[i-1][j-Timer[i]]:
                dp[i][j] = True

for i in range(-(-all//2), all+1):
    if dp[N][i]:
        print(i)
        break


import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor, RandomForestClassifier
from sklearn import metrics
from sklearn.linear_model import LinearRegression
from sklearn.linear_model import Ridge
from sklearn.svm import SVR

class Model:
    regressors = {'random_forest': RandomForestRegressor(n_estimators=10, random_state=None),
                  'linear': LinearRegression(), 'ridge': Ridge(alpha=0.0001), 'svr': SVR()}

    def __init__(self, dataset, len_aln, regressor='random_forest', training_set_size=0.8, weighted=False):
        plt.clf()
        self.data = dataset
        self.X = self.data.features
        self.y = self.data.scores
        if weighted:
            self.weights = self.data.pbm35['WEIGHT']
        else:
            self.weights = None
        self.features = []
        self.l = []
        self.len_aln = len_aln
        self.training_set_size = training_set_size
        self.y_pred, self.r2, self.mse = 3 * [None]
        self.X_train, self.X_test, self.y_train, self.y_test, self.w_train, self.w_test = 6 * [None]

        print("features have shape: ", self.X.shape)
        print("target values have shape: ", self.y.shape)
        self.regressor = Model.regressors[regressor]
        self.train()

    def train(self):
        """
        Splits the data from the Dataset and trains the regressor, also extracting data
        on feature importances
        :return: None
        """
        # splits w/o randomness for training and testing
        if self.weights is not None:
            self.X_train, self.X_test, self.y_train, self.y_test, \
                self.w_train, self.w_test = train_test_split(self.X, self.y.ravel(), self.weights,
                                                             train_size=self.training_set_size,
                                                             random_state=0, shuffle=False)
            self.regressor.fit(self.X_train, self.y_train, self.w_train)
        else:
            self.X_train, self.X_test, self.y_train, \
                self.y_test = train_test_split(self.X, self.y.ravel(), train_size=self.training_set_size,
                                               random_state=0, shuffle=False)
            self.regressor.fit(self.X_train, self.y_train)

        importances = self.regressor.feature_importances_
        std = np.std([tree.feature_importances_ for tree in self.regressor.estimators_], axis=0)
        indices = np.argsort(importances)[::-1]

        # Print the feature ranking
        print("Feature ranking:")
        for f in range(self.X.shape[1]):
            match = ['Shift', 'Slide', 'Rise', 'Tilt', 'Roll', 'Twist']
            if indices[f] < 256:
                feat = 'Presence'
            elif indices[f] in np.arange(256, 256 + (self.len_aln - 3) * 6, 1):
                feat = f'AVG {match[indices[f] % 6]}'
            elif indices[f] in np.arange(256 + (self.len_aln - 3) * 6, 256 + (self.len_aln - 3) * 12, 1):
                feat = f'Diagonal {match[indices[f] % 6]}'
            elif indices[f] >= 256 + (self.len_aln - 3) * 12:
                feat = 'Electro'
            else:
                raise ValueError
            self.l.append(importances[indices[f]])
            self.features.append([feat, importances[indices[f]]])

    def predict(self, testing_dataset=None):
        """
        Performs the prediction on the test data from the internal (default) or external dataset;
        sets the predictions and corresponding errors/correlations as attributes
        :param testing_dataset: Dataset instance, test data to supply for cross-evaluation (optional)
        :return: None
        """
        if testing_dataset is not None:
            self.X_test, self.y_test = testing_dataset.features, testing_dataset.scores
        self.y_pred = self.regressor.predict(self.X_test).reshape(-1, 1)
        self.y_test = self.y_test.reshape(-1, 1)
        if self.weights is not None:
            self.r2 = np.round(metrics.r2_score(self.y_test, self.y_pred, sample_weight=self.w_test), 3)  # with weights
        else:
            self.r2 = np.round(metrics.r2_score(self.y_test, self.y_pred), 3)           # w/o weights
        self.mse = np.round(metrics.mean_absolute_error(self.y_test, self.y_pred), 6)

    def plot(self):
        """
        Plots the prediction vs ground truth
        :return: None
        """
        plt.rc('xtick', labelsize=15)
        plt.rc('ytick', labelsize=15)
        plt.xlabel('Testing')
        plt.ylabel('Predicted')
        # plt.title(f'MSE = {self.mse}, r$^2$ = {self.r2}')
        plt.xlim = (0, 1)
        plt.ylim = (0, 1)
        plt.scatter(self.y_test, self.y_pred, label=f'r$^2$ = {self.r2}')

    @staticmethod
    def show():
        """
        To allow for multiple overlaid scatter plots, show() can be called separately
        :return: None
        """
        plt.legend()
        plt.show()


import glob
import os
import numpy as np
import cv2
import argparse

parser = argparse.ArgumentParser(description='Preprocessing/Visualizing EGTEA Gaze+ gaze annotations')

parser.add_argument('--txtfile', default='./gaze_data', help='path to txt annotations')
parser.add_argument('--datapath', default='dataset', help='path to dataset', required=True)
parser.add_argument('--outputpath', default='output', help='path to output dir', required=True)
parser.add_argument('--p', action='store_false', help='to save data as numpy files')
parser.add_argument('--v', action='store_true', help='to visualize gaze data')

def _str2frame(frame_str, fps=None):
    if fps==None:
        fps = 24

    splited_time = frame_str.split(':')
    assert len(splited_time) == 4

    time_sec = 3600 * int(splited_time[0]) \
               + 60 * int(splited_time[1]) +  int(splited_time[2])

    frame_num = time_sec * fps + int(splited_time[3])

    return frame_num

def parse_gtea_gaze(filename, gaze_resolution=None):
    '''
    Read gaze file in CSV format
    Input:
        name of a gaze csv file
    return
        an array where the each row follows:
        (frame_num): px (0-1), py (0-1), gaze_type
    '''
    if gaze_resolution is None:
        # gaze resolution (default 1280*960)
        gaze_resolution = np.array([960, 1280], dtype=np.float32)

    # load all lines
    lines = [line.rstrip('\n') for line in open(filename)]
    # deal with different version of begaze
    ver = 1
    if '## Number of Samples:' in lines[9]:
        line = lines[9]
        ver = 1
    else:
        line = lines[10]
        ver = 2

    # get the number of samples
    values = line.split()
    num_samples = int(values[4])

    # skip the header
    lines = lines[34:]

    # pre-allocate the array
    # (Note the number of samples in header is not always accurate)
    num_frames = 0
    gaze_data = np.zeros((num_samples*2, 4), dtype=np.float32)

    # parse each line
    for line in lines:
        values = line.split()
        # read gaze_x, gaze_y, gaze_type and frame_number from the file
        if len(values)==7 and ver==1:
            px, py = float(values[3]), float(values[4])
            frame = int(values[5])
            gaze_type = values[6]

        elif len(values)==26 and ver==2:
            px, py = float(values[5]), float(values[6])
            frame = _str2frame(values[-2])
            gaze_type = values[-1]

        else:
            raise ValueError('Format not supported')

        # avg the gaze points if needed
        if gaze_data[frame, 2] > 0:
            gaze_data[frame,0] = (gaze_data[frame,0] + px)/2.0
            gaze_data[frame,1] = (gaze_data[frame,1] + py)/2.0
        else:
            gaze_data[frame,0] = px
            gaze_data[frame,1] = py

        # gaze type
        # 0 untracked (no gaze point available);
        # 1 fixation (pause of gaze);
        # 2 saccade (jump of gaze);
        # 3 unkown (unknown gaze type return by BeGaze);
        # 4 truncated (gaze out of range of the video)
        if gaze_type == 'Fixation':
            gaze_data[frame, 2] = 1
        elif gaze_type == 'Saccade':
            gaze_data[frame, 2] = 2
        else:
            gaze_data[frame, 2] = 3

        num_frames = max(num_frames, frame)

    gaze_data = gaze_data[:num_frames+1, :]

    # post processing:
    # (1) filter out out of bound gaze points
    # (2) normalize gaze into the range of 0-1
    for frame_idx in range(0, num_frames+1):

        px = gaze_data[frame_idx, 0]
        py = gaze_data[frame_idx, 1]
        gaze_type = gaze_data[frame_idx, 2]

        # truncate the gaze points
        if (px < 0 or px > (gaze_resolution[1]-1)) \
           or (py < 0 or py > (gaze_resolution[0]-1)):
            gaze_data[frame_idx, 2] = 4

        px = min(max(0, px), gaze_resolution[1]-1)
        py = min(max(0, py), gaze_resolution[0]-1)

        # normalize the gaze
        gaze_data[frame_idx, 0] = px / gaze_resolution[1]
        gaze_data[frame_idx, 1] = py / gaze_resolution[0]
        gaze_data[frame_idx, 2] = gaze_type

    return gaze_data

def draw_gaze(gaze_data, org_dir_path, dst_dir_path):

    all_jpg_files = []
    for root, dirs, files in os.walk(org_dir_path):
            for file in files:
                if file.endswith(".jpg"):
                    all_jpg_files.append(os.path.join(root, file))

    for jpg in all_jpg_files:
        parent_dir = jpg.split("/")[-2]
        img_idx = int(jpg.split("/")[-1].split(".")[0]) - 1
        start_frame_num = int(parent_dir.split("-")[-2][1:])
        #end_frame_num = int(parent_dir.split("-")[-1][1:])

        img = cv2.imread(jpg)

        h,w,_ = img.shape

        px = int(gaze_data[start_frame_num + img_idx][0] * img.shape[1])
        py = int(gaze_data[start_frame_num + img_idx][1] * img.shape[0])

        if int(gaze_data[start_frame_num + img_idx, 2]) == 1:
            img = cv2.circle(img, (px, py), radius=10, color=(0, 0, 255), thickness=-1)

        dst_path = os.path.join(dst_dir_path, *jpg.split("/")[-2:])
        #dst_path = dst_path.replace(".jpg", ".npy")
        #dst_path = jpg.replace("./", "./gaze_vis/")
        #dst_path = dst_path.replace(".jpg", ".npy")
        dst_dir = "/".join(dst_path.split("/")[0:-1])
        if os.path.exists(dst_dir) == False:
            os.makedirs(dst_dir)

        cv2.imwrite(dst_path, img)

def save_gaze(gaze_data, org_dir_path, dst_dir_path):

    all_jpg_files = []
    for root, dirs, files in os.walk(org_dir_path):
            for file in files:
                if file.endswith(".jpg"):
                    all_jpg_files.append(os.path.join(root, file))

    for jpg in all_jpg_files:
        parent_dir = jpg.split("/")[-2]
        img_idx = int(jpg.split("/")[-1].split(".")[0]) - 1
        start_frame_num = int(parent_dir.split("-")[-2][1:])
        #end_frame_num = int(parent_dir.split("-")[-1][1:])

        dst_path = os.path.join(dst_dir_path, *jpg.split("/")[-2:])
        dst_path = dst_path.replace(".jpg", ".npy")

        if os.path.exists(dst_path):
            continue

        #dst_path = jpg.replace("./", "./gaze_vis/")
        #dst_path = dst_path.replace(".jpg", ".npy")
        dst_dir = "/".join(dst_path.split("/")[0:-1])

        img = cv2.imread(jpg)

        h,w,_ = img.shape
        pmap = np.zeros((h,w), dtype=np.uint8)

        if os.path.exists(dst_dir) == False:
            os.makedirs(dst_dir)

        if start_frame_num + img_idx >= len(gaze_data):
            np.save(dst_path,pmap)
            continue

        px = int(gaze_data[start_frame_num + img_idx][0] * img.shape[1])
        py = int(gaze_data[start_frame_num + img_idx][1] * img.shape[0])

        if int(gaze_data[start_frame_num + img_idx, 2]) == 1:
            pmap[py][px] = 1

        np.save(dst_path,pmap)

if __name__== "__main__":
    args = parser.parse_args()

    all_txt_files = []
    for root, dirs, files in os.walk(args.txtfile):
        for file in files:
            if file.endswith(".txt"):
                all_txt_files.append(os.path.join(root, file))

    for txt in all_txt_files:
        print(txt)
        gaze_data = parse_gtea_gaze(txt)
        org_dir_path = txt.split("/")[-1].split(".")[0]
        dst_dir_path = os.path.join(args.outputpath, org_dir_path)
        org_dir_path = os.path.join(args.datapath, org_dir_path)

        if args.v:
            draw_gaze(gaze_data, org_dir_path, dst_dir_path)
        elif args.p:
            save_gaze(gaze_data, org_dir_path, dst_dir_path)


import asyncio
import discord
from discord import client
from discord import message
from discord.abc import GuildChannel
from discord.ext import commands
from discord.utils import get
from discord_slash import SlashCommand
import logging
import json
from pathlib import Path
from datetime import datetime
from threading import Timer
import time

description = 'A Discord PasteBin Bot'

# Date & Time Variable
timestamp = datetime.now()
gettime = timestamp.strftime(r"%d/%m/%Y %I:%M%p")

cwd = Path(__file__).parents[0]
cwd = str(cwd)
print(f"{cwd}\n-----")

intents = discord.Intents.all()

bot = discord.Client()
config_file = json.load(open(cwd+'/bot_config/config.json'))
bot.config_prefix = config_file['prefix']
bot = commands.Bot(bot.config_prefix, intents=intents, description=description, case_insensitive=True)
slash = SlashCommand(bot)

# Token
token_file = json.load(open(cwd+'/bot_config/token.json'))
bot.token_file = token_file['token']
logging.basicConfig(level=logging.INFO)

# Bot ready log
@bot.event
async def on_ready():
    print(f"-----\nLogged in as: {bot.user.name} : {bot.user.id}\n-----\nCurrent prefix = {config_file['prefix']} & /\n-----\nDate & Time: {gettime}\n-----\nBot is ready\n-----")

# Commands

# Ping
@slash.slash(name='ping', description='Bot Latency Test')
async def ping(message):
    await message.channel.send(f"Pong! {round(bot.latency * 1000)}ms")

# Create a new paste bin channel
@bot.command(name='create', description='Creates a private text channel to use as a PasteBin')
async def create(ctx):
    # Caches author & channel
    author = ctx.author.name.lower()
    author_id = ctx.author.id
    channel = discord.utils.get(ctx.guild.channels, name=author)
    if (channel is None):

        # Deletes user message
        await ctx.message.delete()

        guild = ctx.message.guild
        category = discord.utils.get(ctx.guild.categories, name="userbins")

        # Overwrides channel permission & adds author to channel
        overwrites = {
            guild.default_role: discord.PermissionOverwrite(read_messages=False),
            guild.me: discord.PermissionOverwrite(read_messages=True),
            ctx.author: discord.PermissionOverwrite(read_messages=True, send_messages=True, read_message_history=True)
        }

        # Creates channel
        await guild.create_text_channel(f"{author}", category=category, overwrites=overwrites)

        channel_existing = discord.utils.get(ctx.guild.channels, name=author)
        channel_id = channel_existing.id
        author_channel = bot.get_channel(channel_id)
        emb = discord.Embed(description="This channel will be automaticlly deleted after 10 Minutes. If you wish to delete it sooner, react to this message :recycle:", color=0x4287f5)
        msg = await author_channel.send(embed=emb)
        emoji = '♻'
        await msg.add_reaction(emoji)

        with open("bindb.json", 'a+') as f:

            new_bin_channel = {
                "author": author_id,
                "channel_id": channel_id,
                "message_id": msg.id
            }

            json.dump(new_bin_channel, f, indents=4)

        # Posts confirmation of channel creation
        embededvar0 = discord.Embed(title="PasteBin Created", description=f"{ctx.author.mention}", color=0x2bd642)
        await ctx.send(embed=embededvar0)

        # Deletes channel after 10 Minutes
        await asyncio.sleep(10)
        await channel_existing.delete()

    else:
        # Error message
        embededvar1 = discord.Embed(title="Error", description="You already have a channel created, check under the UserBins category", color=0xFF0000)
        await ctx.channel.send(embed=embededvar1, delete_after=15)

        await ctx.message.delete()
        return

@bot.event
async def on_raw_reaction_delete(payload):
    if payload.member.bot:
        pass

    else:
        emoji = '♻'
        if [emoji] == payload.emoji.name:
            channel = bot.get_channel(payload.channel_id)
            await channel.delete()

# Auto Role on Join
@bot.event
async def on_member_join(member):
    role = discord.utils.get(member.guild.roles, name=config_file['autorole'])
    joined = (f"{gettime}: {member} joined the server and was given {role} role.\n")
    await member.add_roles(role)
    with open('cache/logs.txt', 'a') as f:
        f.write(joined)
    print(joined)

# Bot Login
bot.run(bot.token_file)


import scrapy

class BestsellersSpider(scrapy.Spider):
    name = 'bestsellers'
    allowed_domains = ['www.glassesshop.com']
    start_urls = ['http://www.glassesshop.com/bestsellers/']

    def parse(self, response):
        for glass in response.xpath("//div[@id='product-lists']/div"):
            if glass.xpath(".//a[@href='/buy-one-get-one-free']"):
                continue
            yield {
                'url': glass.xpath(".//div[@class='product-img-outer']/a/@href").get(),
                'img_url': glass.xpath(".//div[@class='product-img-outer']/a/img/@src").get(),
                'name': glass.xpath(".//div[@class='p-title']/a/@title").get(),
                'price': glass.xpath(".//div[@class='p-price']//span/text()").get()
            }

        next_page = response.xpath("//ul[@class='pagination']/li[position() = last()]/a/@href").get()

        if next_page:
            yield scrapy.Request(url=next_page, callback=self.parse)


from django.shortcuts import redirect
from django.urls import path, re_path

from .models import *
from . import views

app_name = 'survey'
urlpatterns = [
    path('', lambda request: redirect('survey:site_overview',
        Checklist.objects.filter(is_active=True).last().id), name='index'),
    re_path(r'^(?P<checklist_id>[0-9]+)/$', views.index, name='site_overview'),
    re_path(r'^(?P<checklist_id>[0-9]+)/(?P<site_id>[0-9]+)/$', views.evaluate, name='evaluate'),
    re_path(r'^(?P<checklist_id>[0-9]+)/summary/$', views.SummaryListView.as_view(), name='summary-list'),
    re_path(r'^(?P<checklist_id>[0-9]+)/summary-by-user/$',
        views.SummaryByUserListView.as_view(), name='summary-by-user-list'),
    re_path(r'^compare/(?P<checklist_id>[0-9]+)/(?P<site_id>[0-9]+)/$', views.CompareListView.as_view(), name='compare'),
    re_path(r'^(?P<checklist_id>[0-9]+)/export/$', views.export, name='export'),
    re_path(r'^discuss/(?P<checklist_id>[0-9]+)/(?P<user_id>[0-9]+)/$', views.DiscussionView.as_view(), name='discuss'),
    re_path(r'^review/(?P<eval_id>[0-9]+)/$', views.ReviewDetailView.as_view(), name='review'),
    re_path(r'^import/$', views.ImportChecklistView.as_view(), name='import-checklist'),
    re_path(r'^apply-import/(?P<checklist_id>[0-9]+)/$', views.apply_import, name='apply-import'),
    re_path(r'^ajax/clear-discussion/(?P<answerchoice_id>[0-9]+)/$', views.clear_discussion, name='clear-discussion'),
]