import contextlib
import threading
import socket
import struct

from utils.utils import Constants
from repository.sqlite_manager import SQLiteManager as SQLiteManager

class Historian:
    def __init__(self):
        self.gw_hist_fd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.hist_serverapp_fd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.server_app_dst = (Constants.HISTORIAN_SERVER_APP_HOST,
                Constants.HISTORIAN_SERVER_APP_PORT)
        self.sqlite_instance = SQLiteManager()

    def up_server(self):
        self.gw_hist_fd.bind((Constants.GATEWAY_HISTORIAN_HOST, Constants.GATEWAY_HISTORIAN_PORT))
        print("Historian UDP server up and listening")

        while(True):
            bytesAddressPair = self.gw_hist_fd.recvfrom(Constants.BUFFER_SIZE)
            message = bytesAddressPair[0]
            address = bytesAddressPair[1]

            unpacked_message = struct.unpack(Constants.PACK_POSITION_T_STRING, message)
            clientMsg = "Message from Client: {}".format(unpacked_message)
            clientIP  = "Client IP Address: {}".format(address)
            print(clientMsg)
            print(clientIP)
            self.__record_database__(unpacked_message)

        return

    def __record_database__(self, position_list):
        self.sqlite_instance.insert_position_into_db(position_list)

    def __request_database__(self, id, num_samples):
        return self.sqlite_instance.request_position_by_id(id, num_samples)

    def up_server_app(self):
        self.hist_serverapp_fd.bind(self.server_app_dst)
        print("Historian UDP server_app up and listening")

        while(True):
            try:
                bytesAddressPair = self.hist_serverapp_fd.recvfrom(Constants.BUFFER_SIZE)
                message = bytesAddressPair[0]
                address = bytesAddressPair[1]

                historical_data_request_t = struct.unpack('ii', message)
                binary_response = self.__request_database__(int(historical_data_request_t[0]), int(historical_data_request_t[1]))
                self.hist_serverapp_fd.sendto(binary_response, address)
            except Exception as e:
                print(str(e))
                continue


from django.conf.urls import url

from django.conf import settings
from django.conf.urls.static import static

from . import views

app_name = 'app'
urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^sort_by_id/$', views.sort_by_id, name='sort_by_id'),
    url(r'^sort_by_partner/$', views.sort_by_partner, name='sort_by_partner'),
    url(r'^(?P<status>[0-9]+)/$', views.filter_status, name='filter_status'),
    url(r'^edit/(?P<project_id>[0-9]+)/$', views.edit, name='edit'),
    url(r'^add/$', views.add, name='add'),
    url(r'^add_device/$', views.add_device, name='add_device'),
    url(r'^search/$', views.search, name='search'),
    url(r'^report/$', views.report, name='report'),

    # url(r'^add/$', views.AddView.as_view(), name='add'),
    # url(r'^get_name/$', views.get_name, name='get_name'),
    # url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),

] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)


import argparse, os
from reader import Reader

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Reader of MongoDB documents.')

    parser.add_argument('--start', action='store', type=int, default=0,
                    help='The document number to start with (default 0)')
    parser.add_argument('--end', action='store', type=int,
                    help='The document number to end with (default last)')
    parser.add_argument('--size', action='store', type=int, default=10,
                    help='The document count to handle (default 10)')
    parser.add_argument('--config', action='store', type=str,
                    help='The configuration file to use.')
    args = parser.parse_args()
    filename = os.path.dirname(os.path.realpath(__file__)) + args.config
    print("filename", filename)
    reader = Reader(args.start, args.end, args.size, filename)
    reader.run()


import json
import boto3
from boto3.dynamodb.conditions import Key, Attr
from decimal import Decimal

dynamo_client = boto3.resource('dynamodb')
broker_table = dynamo_client.Table('broker_users')
carrier_table = dynamo_client.Table('carrier_users')

response = carrier_table.scan()
carrier_emails = []
for i in response['Items']:
    carrier_emails.append(i['email'])

def lambda_handler(event, context):
    userEmail = event["userEmail"]
    broker = broker_table.get_item(
        Key={
            "email": userEmail
        }
    )
    contact_email_list = broker.get('Item', {}).get('contacts', [])
    new_contact_list = []
    new_user_list = []
    for contact in event.get('contacts', []):
        if contact['Email'] not in carrier_emails:
            newCarrier = {}
            newCarrier['email'] = contact['Email']
            newCarrier['companyName'] = contact.get('Company Name', '')
            newCarrier['carrierName'] = contact.get('First Name', '') + ' ' + contact.get('Last Name', '')
            newCarrier['contacts'] = [userEmail]
            newCarrier['temp'] = True
            carrier_table.put_item(
                Item=newCarrier
            )
            new_contact_list.append(contact)
            new_user_list.append(contact)

        if contact['Email'] not in contact_email_list:
            contact_email_list.append(contact['Email'])
    try:
        broker_table.update_item(
            Key={'email': userEmail},
            UpdateExpression='SET #attr1 = :val1',
            ConditionExpression=(
                'email = :email'
            ),
            ExpressionAttributeNames={'#attr1': 'contacts'},
            ExpressionAttributeValues={':email': userEmail, ':val1': contact_email_list},
            ReturnValues='UPDATED_NEW'
        )
        return {
            'statusCode': 200,
            'newContacts': new_user_list
        }
    except Exception as e:
        return {
            "statusCode": 500,
            "message": e
        }


import os
import json
import click
from datetime import datetime
from flask_migrate import Migrate
from app import create_app, db
from app.models import User, Event, Exercise

app = create_app(os.getenv('FLASK_CONFIG') or 'default')
migrate = Migrate(app, db)

@app.shell_context_processor
def make_shell_context():
    return dict(db=db, User=User, Exercise=Exercise)

@app.cli.command()
def test():
    """Run the unit tests."""
    # import unittest
    # tests = unittest.TestLoader().discover('tests')
    # unittest.TextTestRunner(verbosity=2).run(tests)

    import pytest
    pytest.main(['tests/'])

@app.cli.command()
@click.option('--drop_first', default=False)
def createdb(drop_first):
    """Creates a database."""
    if drop_first:
        db.drop_all()
    db.create_all()

@app.cli.command()
def seeddb():
    user = User(email='ben@domain.com',
                first_name='Ben',
                last_name='Randerson')
    user.set_password('test')
    db.session.add(user)
    EVENTS = json.load(open('events.json'))
    for event in EVENTS:
        date = datetime.strptime(EVENTS[event]['date'], '%Y-%m-%d').date()
        d = EVENTS[event]['date']
        e = Event(name=event,
                  distance=EVENTS[event]['distance'],
                  date=date)
        db.session.add(e)
    db.session.commit()

@app.cli.command()
def clean():
    """Remove *.pyc and *.pyo files recursively starting at current directory.
    """
    for dirpath, dirnames, filenames in os.walk('.'):
        for filename in filenames:
            if filename.endswith('.pyc') or filename.endswith('.pyo'):
                full_pathname = os.path.join(dirpath, filename)
                print('Removing {}'.format(full_pathname))
                os.remove(full_pathname)


#!/usr/bin/env python3
import logging

import rebrand_lib as lib

# Three / four letter abbreviation of new block chain. Example: kor, nano, ban
abbreviation = lib.get_env_variable('ABBREVIATION')

# Default boompow payout address
boompow_payout_address = lib.get_env_variable('BOOMPOW_PAYOUT_ADDRESS')

# Fully qualified domain name
domainsvc = lib.get_env_variable('DOMAINSVC')

work_threshold = lib.get_env_variable('WORK_THRESHOLD')
work_thresholds = work_threshold.split(",")
work_threshold_default = lib.get_env_variable('WORK_THRESHOLD_DEFAULT')

ignore_list = [
    "build",
    "git",
    "github",
    "miniupnp",
    "crypto",
    "lmd",
    "gtest",
    "cpptoml",
    "flatbuffers",
    "rocksd",
    "idea",
    "docker",
    "venv",
    "cmake-build-debug",
    "rebrand_nault.py",
    "gitmodules",
    "gitignore",
    "README.md",
    "SECURITY.md",
    "rep_weights_beta",
    "rep_weights_live",
    "clang-format",
    "env_local",
    "env_example",
    "node_modules",
    "nanocurrency-js"
]

words = [
    [b"previous, difficulty='fffffff800000000'", b"previous, difficulty='%s'" % str.encode(work_threshold_default)],
    [b"base_difficulty='fffffe0000000000'", b"base_difficulty='%s'" % str.encode(work_thresholds[0])],
    [b"DEFAULT_WORK_DIFFICULTY = 'fffffe0000000000'", b"DEFAULT_WORK_DIFFICULTY = '%s'" % str.encode(work_thresholds[0])],
    [b'"difficulty": "fffffe0000000000"', b'"difficulty": "%s"' % str.encode(work_thresholds[0])],
    [b'default `fffffe0000000000`', b'default `%s`' % str.encode(work_thresholds[0])],
]
lib.replace_all(words, ignore_list, "/NanoRPCProxy")

bananoPublicAddress = "    p = re.compile('^(ban)_[13]{1}[13456789abcdefghijkmnopqrstuwxyz]{59}$')"
bananoPublicAddressReplace = "    p = re.compile('^(%s)_[13]{1}[13456789abcdefghijkmnopqrstuwxyz]{59}$')" % abbreviation
lib.find_and_replace("%sboompow/client/config_parse.py" % lib.cwd(),
                 str.encode(bananoPublicAddress),
                 str.encode(bananoPublicAddressReplace))

payoutAddress = "ban_1boompow14irck1yauquqypt7afqrh8b6bbu5r93pc6hgbqs7z6o99frcuym"
payoutAddressReplace = "%s_123...1234" % abbreviation
lib.find_and_replace("%sboompow/client/run_windows.bat" % lib.cwd(),
                 str.encode(payoutAddress),
                 str.encode(payoutAddressReplace))

notAValidAddress = 'msg = "%r is not a valid BANANO address" % string'
notAValidAddressReplace = 'msg = "%r is not a valid address" % string'
lib.find_and_replace("%sboompow/client/config_parse.py" % lib.cwd(),
                 str.encode(notAValidAddress),
                 str.encode(notAValidAddressReplace))

addressRegex = "address_regex = '(?:ban)(?:_)(?:1|3)(?:[13456789abcdefghijkmnopqrstuwxyz]{59})'"
addressRegexReplace = "address_regex = '(?:%s)(?:_)(?:1|3)(?:[13456789abcdefghijkmnopqrstuwxyz]{59})'" % abbreviation
lib.find_and_replace("%sboompow/server/bpow/validators.py" % lib.cwd(),
                 str.encode(addressRegex),
                 str.encode(addressRegexReplace))

abbreviation_len = len(abbreviation)
address_len = 64

if abbreviation_len == 3:
    address_len = 64
elif abbreviation_len == 4:
    address_len = 65
else:
    logging.error("Wrong abbreviation length!")

validateChecksumxrb1 = "if len(address) == 64 and address[:4] == 'ban_':"
validateChecksumxrb1Replace = "if len(address) == %s and address[:%s] == '%s_':" % (address_len,
                                                                                str(abbreviation_len+1),
                                                                                abbreviation)
lib.find_and_replace("%sboompow/server/bpow/validators.py" % lib.cwd(),
                 str.encode(validateChecksumxrb1),
                 str.encode(validateChecksumxrb1Replace))

validateChecksumxrb2 = "acrop_key = address[4:-8]"
validateChecksumxrb2Replace = "acrop_key = address[%s:-8]" % str(abbreviation_len+1)
lib.find_and_replace("%sboompow/server/bpow/validators.py" % lib.cwd(),
                 str.encode(validateChecksumxrb2),
                 str.encode(validateChecksumxrb2Replace))

requirementsSerever = """ujson
uvloop
aiohttp
aioredis
amqtt
websockets
requests
asyncio-throttle
nanolib
bitstring
redis"""
requirementsSereverReplace = """aiohttp==3.7.4.post0
aioredis==1.3.1
amqtt==0.10.0a3
async-timeout==3.0.1
asyncio-throttle==1.0.2
attrs==21.2.0
bitstring==3.1.7
certifi==2021.5.30
chardet==4.0.0
docopt==0.6.2
ed25519-blake2b==1.4
hiredis==2.0.0
idna==2.10
multidict==5.1.0
nanolib==0.4.3
passlib==1.7.4
py-cpuinfo==8.0.0
PyYAML==5.4.1
redis==3.5.3
requests==2.25.1
six==1.16.0
transitions==0.8.8
typing-extensions==3.10.0.0
ujson==4.0.2
urllib3==1.26.5
uvloop==0.15.2
websockets==8.1
yarl==1.6.3"""
lib.find_and_replace("%sboompow/server/requirements.txt" % lib.cwd(),
                     str.encode(requirementsSerever),
                     str.encode(requirementsSereverReplace))
# replace urls
urls = [
    [b"bpow.banano.cc", b"%s-bpow.%s" % (str.encode(abbreviation), str.encode(domainsvc))],
    [b"chat.banano.cc", b"%s-chat.%s" % (str.encode(abbreviation), str.encode(domainsvc))],
    [b"https://banano.cc", b"https://%s.%s" % (str.encode(abbreviation), str.encode(domainsvc))],
]
lib.replace_all(urls, ignore_list, "/boompow")


from django.core.paginator import Paginator

def paginate(data, get_params) -> dict:
    page = get_params['page'] if 'page' in get_params else 1
    paginator = Paginator(data, get_params['page_size'])

    page = paginator.get_page(page)
    return {
        'page': page.number,
        'page_size': get_params['page_size'],
        'total_pages': paginator.num_pages,
        'data': page.object_list,
    }


# -*- coding: utf-8 -*-
import os
import re
import sys
import json
import subprocess
import requests
from datetime import datetime
from dateutil import parser

# Add xcall folder to path so we can import it since
# we're using it as a submodule.
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "xcall"))
import xcall

BEAR_API_TOKEN = os.getenv("BEAR_API_TOKEN")
if BEAR_API_TOKEN is None:
    raise Exception("Missing API Token")

PLANNER_TAG = "day planner"
TITLE_DAY_FORMAT = "%A %B %-d, %Y"
NOTE_BODY = u"""
## Todo:
{todo_items}

## Notes:

## Today's Agenda:
{agenda}
## Weather Forecast:
{weather}
"""

def get_daily_agenda():
    command = ['icalbuddy -iep datetime,title,location -b "- " -ic patrick@noom.com -nc eventsToday']
    return subprocess.check_output(command, shell=True)

def get_weather():
    r = requests.get("http://wttr.in/?0&T")
    return u"```\n{}```".format(r.text)

def format_note():
    title = datetime.now().strftime(TITLE_DAY_FORMAT)
    tags = ",".join([PLANNER_TAG])
    agenda = get_daily_agenda()
    weather = get_weather()

    todos = get_unfinished_todo_items()
    if not todos:
        todos = ["- [] Start doing something"]

    body = NOTE_BODY.format(agenda=agenda, weather=weather, todo_items="\n".join(todos))

    return {
        "title": title,
        "tags": tags,
        "text": body,
        "open_note": True,
        "pin": True,
        "timestamp": True
    }

def get_existing_notes():
    search_term = datetime.now().strftime(TITLE_DAY_FORMAT)
    contents = xcall.xcall('bear', 'search', {"tag": PLANNER_TAG, "token": BEAR_API_TOKEN, "show_window": False, "term": search_term})
    notes = json.loads(contents['notes'])
    if len(notes) > 0:
        return contents['notes'][0]
    return None

def get_last_note():
    contents = xcall.xcall('bear', 'search', {"tag": PLANNER_TAG, "token": BEAR_API_TOKEN, "show_window": "no"})
    notes = json.loads(contents['notes'])
    last_note = None
    last_note_creation_date = None
    for note in notes:
        creation_date = parser.parse(note['creationDate'])
        if not last_note:
            last_note = note
            last_note_creation_date = creation_date
        else:
            if creation_date > last_note_creation_date:
                last_note = note
                last_note_creation_date = creation_date
    note = xcall.xcall('bear', 'open-note', {"id": last_note['identifier'], "new_window": "no", "show_window": "no"})
    return note

def get_unfinished_todo_items():
    last_note = get_last_note()
    note_body = last_note['note']
    lines = note_body.split('\n')
    pattern = re.compile('(?:- \[ \] )(.*)')

    existing_todos = []
    for line in lines:
        match = pattern.match(line)
        if match:
            existing_todos.append(match.group(0))

    return existing_todos

def create_daily_note():
    parameters = format_note()
    contents = xcall.xcall('bear', 'create', parameters)
    return contents

def main():
    # TODO: Get unchecked todo items from previous day and add them to current todo.
    # TODO: Remove morning time and evening time from calendar.
    if not get_existing_notes():
        create_daily_note()
        print("Daily note created!")
    else:
        print("Daily note already exists.")

if __name__ == "__main__":
    main()


import functools
import inspect

from collections import defaultdict
from typing import Callable, Dict, Optional

from termcolor import colored

from zelos import HookType
from zelos.exceptions import ZelosException
from zelos.plugin import ArgFactory, IKernel

from .syscalls import syscall_utils as sys_utils
from .syscalls.arg_strings import get_arg_string

def construct_kernel(arch, z):
    kernel_class = {
        "x86": X86Kernel,
        "x86_64": X86_64Kernel,
        "arm": ARMKernel,
        "mips": MIPSKernel,
    }.get(arch, None)

    if kernel_class is None:
        return None
    return kernel_class(z)

class LinuxKernel(IKernel):
    def __init__(self, arch, engine):
        super(LinuxKernel, self).__init__(engine)
        self.arch = arch
        self.call_map = self.__load_linux_syscall_maps(arch)
        self._name2syscall_func = self._load_linux_syscall_funcs()
        self.rev_map = {v: k for k, v in self.call_map.items()}

        self.arg_factory = ArgFactory(
            functools.partial(get_arg_string, self.z)
        )

        self.socketcall_dict = {
            1: "socket",
            2: "bind",
            3: "connect",
            4: "listen",
            5: "accept",
            6: "getsockname",
            7: "getpeername",
            8: "socketpair",
            9: "send",
            10: "recv",
            11: "sendto",
            12: "recvfrom",
            13: "shutdown",
            14: "setsockopt",
            15: "getsockopt",
            16: "sendmsg",
            17: "recvmsg",
            18: "accept4",
            19: "recvmmsg",
            20: "sendmmsg",
        }

        # These are processes that are exited, and so a parent process
        # can wait on them.
        # parent_pid -> child_pid
        self.child_state_changes = defaultdict(list)

    def _load_linux_syscall_funcs(
        self,
    ) -> Dict[str, Callable[[any], Optional[int]]]:
        """
        Returns map of name -> syscall implementation.
        """
        from .syscalls import syscalls as linux_syscall_module

        linux_syscalls = inspect.getmembers(
            linux_syscall_module, inspect.isfunction
        )

        return {
            name.partition("sys_")[-1]: func
            for name, func in linux_syscalls
            if name.startswith("sys_")
        }

    def __load_linux_syscall_maps(self, arch):
        """
        Loads the list of supported syscalls from the syscalls table.
        """
        from .syscalls.syscalls_table import cols, table

        try:
            i = cols.index(arch)
        except ValueError:
            raise ZelosException(f"Invalid architecture '{arch}'")

        return {k: v[i] for (k, v) in table.items() if v[i] != -1}

    def handle_syscall(self, process):
        """
        Additionally translate `socketcall` syscalls to their target
        socket system call, e.g. `recv`, for the purpose of syscall
        breaks. This ensures that breakpoints for `recv` will be
        triggered both for `recv` and `socketcall` syscalls that invoke
        `recv`, etc.
        """
        sys_num = self.get_syscall_number()
        sys_name = self.find_syscall_name_by_number(sys_num)
        if sys_name == "socketcall":
            socketcall_args = self.get_last_syscall_args()
            args = self.get_args(
                [("int", "call"), ("unsigned long *", "callargs")],
                sys_num=sys_num,
            )
        status = super(LinuxKernel, self).handle_syscall(process)
        if sys_name == "socketcall":
            socketcall = self.socketcall_dict.get(args.call, None)
            if socketcall is not None:
                self.last_syscall_args = socketcall_args
                self._handle_syscall_break(socketcall)
        return status

    def set_errno(self, val):
        pass

    def _get_socketcall_args(
        self, process, func_name, args_addr, arg_list, arg_string_overrides={}
    ):
        # If calling these syscalls directly, get_args the old
        # fashioned way.
        if args_addr < 0:
            return self.get_args(arg_list, arg_string_overrides)

        arg_vals = [
            process.memory.read_int(args_addr + i * 4)
            for i in range(len(arg_list))
        ]
        args = self.arg_factory.gen_args(
            arg_list, arg_vals, arg_string_overrides=arg_string_overrides
        )
        self.last_syscall_args = args
        self._print_socket_syscall(func_name, args)
        return args

    def _print_socket_syscall(self, func_name, args):
        s = colored(f"{func_name}", "white", attrs=["bold"]) + f" ( {args} )"
        self.z.plugins.trace.print("SOCKET SYSCALL", s)

    ####################
    # HELPER FUNCTIONS #
    ####################

    def get_args(self, arg_list, arg_string_overrides={}, sys_num=None):
        """
        Gets arguments according to linux syscall calling convention
        """
        z = self.z
        if sys_num is None:
            sys_num = self.get_syscall_number()
        reg_list = self._REG_ARGS

        arg_regs = reg_list[: len(arg_list)]

        arg_vals = [z.current_thread.get_reg(arg) for arg in arg_regs]

        # Get the rest of the arguments off of the stack
        i = len(arg_vals)
        while len(arg_vals) < len(arg_list):
            arg_vals.append(self.emu.getstack(i))
            i += 1
        args = self.arg_factory.gen_args(
            arg_list, arg_vals, arg_string_overrides=arg_string_overrides
        )
        self.last_syscall_args = args
        return args

class X86Kernel(LinuxKernel):
    def __init__(self, engine):
        super(X86Kernel, self).__init__("x86", engine)

        def syscall_handler_wrapper(current_process, *args, **kwargs):
            self.handle_syscall(current_process)

        engine.interrupt_handler.register_interrupt_handler(
            0x80, syscall_handler_wrapper
        )

    _REG_NUMBER = "eax"
    _REG_ARGS = ["ebx", "ecx", "edx", "esi", "edi", "ebp"]
    _REG_RETURN = "eax"
    _REG_RETURN_2 = "edx"

    def get_syscall_number(self):
        return self.emu.get_reg("eax")

    def set_return_value(self, value):
        self.emu.set_reg("eax", value)

    def return_addr(self):
        return self.emu.getIP()

class X86_64Kernel(LinuxKernel):
    def __init__(self, engine):
        super(X86_64Kernel, self).__init__("x86_64", engine)

        def handle_syscall_callback(zelos):
            current_process = engine.current_process
            """
            We need to execute a syscall at this point, however,
            certain syscalls may not be runnable within a hook (they
            cause zebracorn to execute code which is not allowed in a
            hook)
            """
            handle_syscall_closure = functools.partial(
                self.handle_syscall, current_process
            )
            current_process.scheduler.stop_and_exec(
                "handle syscall", handle_syscall_closure
            )
            return True

        # Syscalls are made using the syscall instruction. Unicorn does
        # not catch these by default though.
        engine.hook_manager.register_inst_type_hook(
            HookType._INST.X86_SYSCALL,
            handle_syscall_callback,
            name="x64_syscall_hook",
        )

    _REG_NUMBER = "rax"
    _REG_ARGS = ["rdi", "rsi", "rdx", "r10", "r8", "r9"]
    _REG_RETURN = "rax"
    _REG_RETURN_2 = "rdx"

    def get_syscall_number(self):
        return self.emu.get_reg("rax")

    def handle_syscall(self, *args, **kwargs):
        t = self.z.current_thread
        addr = t.getIP()
        super().handle_syscall(*args, **kwargs)

        if addr == t.getIP():

            def set_ip():
                t.setIP(addr + 2)

            self.z.scheduler.stop_and_exec("handle_syscall", set_ip)

    def set_return_value(self, value):
        self.emu.set_reg("rax", value)

    def set_errno(self, val: int):
        fs_base = sys_utils.get_fs(self.z.current_process)
        errno_location = fs_base - 0x80
        self.z.memory.write_int(errno_location, val)

    def return_addr(self):
        return self.emu.getIP() + 2

    def pause_syscall(self, process, condition=None):
        """
        Defines what happens when the pause syscall exception is
        received
        """
        super().pause_syscall(process, condition=condition)
        return

class ARMKernel(LinuxKernel):
    def __init__(self, engine):
        super(ARMKernel, self).__init__("arm", engine)

        def syscall_handler_wrapper(current_process, *args, **kwargs):
            self.handle_syscall(current_process)

        engine.hook_manager.register_interrupt_hook(
            syscall_handler_wrapper, intno=0x2
        )

    _REG_NUMBER = "r7"
    _REG_ARGS = ["r0", "r1", "r2", "r3", "r4", "r5", "r6"]
    _REG_RETURN = "r0"
    _REG_RETURN_2 = "r1"

    def get_syscall_number(self):
        # Some syscalls are passed through svc, and these seem to be the
        # "old abi" (https://w3challs.com/syscalls/?arch=arm_strong)
        # Discussion on difference between oldabi and eabi:
        #   https://lists.gnu.org/archive/html/qemu-devel/2009-01/msg01512.html
        # More discussion:
        #   https://www.raspberrypi.org/forums/viewtopic.php?t=158915
        svc_inst = self.z.disas(self.z.current_thread.getIP() - 4, 4)[0]
        if svc_inst.insn_name() == "svc":
            svc_val = svc_inst.operands[0].imm
            if svc_val != 0:
                return svc_val - 0x900000
        else:
            self.logger.notice(
                f"Why was there an exception here if the last instruction "
                f"wasn't a syscall {self.z.current_thread.getIP():x}"
            )
        val = self.emu.get_reg("r7")
        return val

    def set_return_value(self, value):
        self.emu.set_reg("r0", value)

    def return_addr(self):
        # (V) we had this as ip+4 initially, but found that to be wrong.
        # Double check that this is consistently correct.
        return self.emu.getIP()

    # arch/arm/kernel/entry-armv.S:
    # __kuser_get_tls: @ 0xffff0fe0
    # #if !defined(CONFIG_HAS_TLS_REG) && !defined(CONFIG_TLS_REG_EMUL)
    #     ldr r0, [pc, #(16 - 8)] @ TLS stored at 0xffff0ff0
    # #else
    #     mrc p15, 0, r0, c13, c0, 3 @ read TLS register
    # #endif
    #     usr_ret lr

    def _kuser_get_tls(self):
        self.logger.info("Called kuser_get_tls")
        tls = self.emu.get_reg("c13_c0_3")
        self.set_return_value(tls)
        self.emu.setIP(self.emu.get_reg("lr"))

    def _kuser_cmpxchg(self):
        self.logger.info("Called kuser_cmpxchg")
        oldval = self.emu.get_reg("r0")
        newval = self.emu.get_reg("r1")
        ptr = self.emu.get_reg("r2")

        d_ptr = self.z.memory.read_int(ptr)

        if d_ptr != oldval:
            CPSR_CF_CLEAR = self.emu.get_reg("cpsr") & 0xDFFFFFFF  # CPSR[29]
            self.emu.set_reg("cpsr", CPSR_CF_CLEAR)
            self.emu.setIP(self.emu.get_reg("lr"))
            self.set_return_value(1)
        else:
            self.z.memory.write_int(ptr, newval)
            CPSR_CF_SET = self.emu.get_reg("cpsr") | 0x20000000  # CPSR[29]
            self.emu.set_reg("cpsr", CPSR_CF_SET)
            self.emu.setIP(self.emu.get_reg("lr"))
            self.set_return_value(0)

    def _kuser_memory_barrier(self):
        self.logger.info("Called kuser_memory_barrier")
        self.emu.setIP(self.emu.get_reg("lr"))

    def _kuser_cmpxchg64(self):
        self.logger.notice("Reached kuser_cmpxchg64, needs to be implemented")
        self.emu.setIP(self.emu.get_reg("lr"))

class MIPSKernel(LinuxKernel):
    def __init__(self, engine):
        super(MIPSKernel, self).__init__("mips", engine)

        def syscall_handler_wrapper(current_process, *args, **kwargs):
            self.handle_syscall(current_process)

        engine.hook_manager.register_interrupt_hook(
            syscall_handler_wrapper, intno=0x11
        )

    _REG_NUMBER = "v0"
    _REG_ARGS = ["a0", "a1", "a2", "a3"]
    _REG_RETURN = "v0"
    _REG_RETURN_2 = "v1"

    def handle_syscall(self, *args, **kwargs):
        super(MIPSKernel, self).handle_syscall(*args, **kwargs)

        # Mimicking qemu user behavior (specifically -1133)
        # github.com/qemu/qemu/blob/master/linux-user/mips/cpu_loop.c
        unsigned_neg1 = 2 ** (self.z.state.bytes * 8) - 1
        retval = self.get_return_value()
        if unsigned_neg1 >= retval >= (-1133 & unsigned_neg1):
            self.emu.set_reg("a3", 1)
            self.set_return_value(-retval)
        else:
            self.emu.set_reg("a3", 0)

        return True

    def get_syscall_number(self):
        return self.emu.get_reg("v0")

    def set_return_value(self, value):
        self.emu.set_reg("v0", value)

    def get_return_value(self):
        return self.emu.get_reg("v0")

    def return_addr(self):
        return self.emu.getIP()


import os
from yaml import  load
from configparser import ConfigParser
import json
from  copy import copy
import hashlib
import platform
from requests.structures import CaseInsensitiveDict
from mlib.logger import  myLog
from mlib.build_in import do_validation
from mconf.setting import PARAM_PATH
from collections import OrderedDict
from mlib.m_expection   import *
import re
logger = myLog.getLog()

variable_regexp = r"\$([\w_]+)"

#获取可变参数
def extract_variables(content):
    """ extract all variable names from content, which is in format $variable
    @param (str) content
    @return (list) variable name list

    e.g. $variable => ["variable"]
         /blog/$postid => ["postid"]
         /$var1/$var2 => ["var1", "var2"]
         abc => []
    """
    try:
        result_list=re.findall(variable_regexp, content)
        return result_list[0]
    except TypeError:
        return []
# 操作文件类
class Operate_File():

    def __init__(self,file_name):
        if not file_name:
            logger.m_error('文件名不能为空,文件名为{}'.format(file_name))
        else:
            self.file_name=file_name
    #获取路径
    def get_path(self):
        path=os.path.dirname( __file__)
        parent_path=os.path.dirname(path)
        grand_path=os.path.join(parent_path,self.file_name)
        if platform.system() == 'Windows':
            logger.m_debug('系统为windows')
            if '\..' in grand_path:
                final_path=grand_path.replace('\../','/')
                return final_path
        elif platform.system() == 'Linux':
            if '/../' in grand_path:
                final_path = grand_path.replace('/../','/')

                logger.m_debug('linux上地址为{}'.format(grand_path))
                return final_path
        else:
            logger.m_error('暂未考虑其他平台的处理')
    #读取文件
    def read_file(self):
        path=self.get_path()
        logger.m_debug('路径为{}'.format(path))
        if  'yaml'in self.file_name:
            try:
                with open(path, 'rb') as pf:
                    data=load(pf)
                return data
            except Exception as e:
                logger.m_error('读取出错了，{}'.format(e))
                return  e
        elif 'ini' in self.file_name:
            config=ConfigParser()
            try:
                config.read(path)
                return config
            except Exception as e:
                logger.m_error('读取出错了，{}'.format(e))
                return  e

def query_json(query,json_content,  delimiter='.'):
    """ Do an xpath-like query with json_content.
    @param (json_content) json_content
        json_content = {
            "ids": [1, 2, 3, 4],
            "person": {
                "name": {
                    "first_name": "Leo",
                    "last_name": "Lee",
                },
                "age": 29,
                "cities": ["Guangzhou", "Shenzhen"]
            }
        }
    @param (str) query
        "person.name.first_name"  =>  "Leo"
        "person.cities.0"         =>  "Guangzhou"
    @return queried result
    """
    if json_content == "":
        raise ResponseError("response content is empty!")

    try:
        for key in query.split(delimiter):
            if isinstance(json_content, list):
                json_content = json_content[int(key)]
            elif isinstance(json_content, (dict, CaseInsensitiveDict)):
                json_content = json_content[key]
            else:
                raise ParseResponseError(
                    "response content is in text format! failed to query key {}!".format(key))
    except (KeyError, ValueError, IndexError):
        raise ParseResponseError("failed to query json when extracting response!")

    return json_content

#解决接口参数依赖上个接口返回的问题
def assemble_parm(data_dic):
    if isinstance(data_dic,dict):
        for k, v in data_dic.items():
            if str(v).startswith('$'):
                logger.m_info('v是需要提替换%s'%v)
                tmp = fetch_extract()
                v=v[1:]
                logger.m_info('tmp为%s'%tmp)
                data_dic[k] = tmp[v]
    elif isinstance(data_dic,str):
        if '$' in data_dic:
            tmp = fetch_extract()#获取上个接口返回的参数，字典形式
            parm_str = extract_variables(data_dic)#提取参数
            new_str = tmp[parm_str]
            old_str='$'+parm_str
            data_dic = data_dic.replace(old_str,new_str)

        logger.m_info('最终结果为%s'%data_dic)
    return data_dic

# 提取依赖参数
def extract_response(query,response):
    if  not isinstance(query,list):
        raise ParamsError('1should be list')
    result_list = {}
    for item in query:
        if not isinstance(item, dict):
            raise ParamsError('2should be list')
        for k, v in item.items():

            #print('v是%s' %v)
            item[k] = query_json(v,response)
            result_list.update(item)

    return result_list

def keep_extract(result_list,response):
    if not isinstance(result_list,list):
        raise ParamsError('1should be list')
    e = extract_response(result_list, response)
    with open(PARAM_PATH, 'w') as f:
        f.write(json.dumps(e))
def fetch_extract():
    with open(PARAM_PATH, 'r') as f:
        result = f.read()
        content = json.loads(result)

        return content

# 从接口提取返回值，为做验证用
def validate_response(query,response):
    if  not isinstance(query,list):
        raise ParamsError('1should be list')
    result_list = []
    for item in query:
        if not isinstance(item, dict):
            raise ParamsError('2should be list')
        for k, v in item.items():
            tmp = copy(v)
            if not isinstance(v,list):
                raise ParamsError('3should be list')
            qe = v[0]

            tmp[0] = query_json(qe,response)
            tmp.insert(0,k)
            result_list.append(tmp)

    return result_list

# 验证期望值和返回值
def m_check(mapping):
    if  not isinstance(mapping,list):
        raise ParamsError('should be list')
    for item in mapping:
        s=do_validation(item[0],item[1],item[2])
        return s

#md5加密
def md5_str(str):
    b_str=bytes(str,encoding='utf-8')
    return hashlib.md5(b_str).hexdigest()

if __name__=='__main__':
    #op =operate_File('../TestData/gm/valid.yaml')
    #d=op.read_file()

    check_data={
            'test_name':'用户信息查询',
            'parm':{
                'service':'bind_url',
                'body':[{
                    'index':{
                        'name':'shen',
                        'vals':[111111,222222]
                    }
                    }]
                }

            }

    #op = operate_File('../data/test_one/extract')
    #op.write_file(json.dumps(check_data))

    p_str = 'parm.body.0.index.vals.1'

    #print(query_json(p_str,check_data))
    print(fetch_extract())


import cairo
import logging
import os
from gettext import gettext as _

from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import GObject
from gi.repository import GdkPixbuf
from gi.repository import WebKit

from urlparse import urlparse

from softwarecenter.utils import SimpleFileDownloader
from softwarecenter.ui.gtk3.em import StockEms
from softwarecenter.ui.gtk3.drawing import rounded_rect
from softwarecenter.ui.gtk3.utils import point_in
import softwarecenter.paths

LOG = logging.getLogger(__name__)

_asset_cache = {}
_HAND = Gdk.Cursor.new(Gdk.CursorType.HAND2)

EXHIBIT_HTML = """

%(title)s

 %(subtitle)s

"""

class FeaturedExhibit(object):

    def __init__(self):
        self.id = 0
        self.package_names = ("armagetronad,calibre,cheese,homebank,"
            "stellarium,gimp,inkscape,blender,audacity,gufw,frozen-bubble,"
            "fretsonfire,moovida,liferea,arista,gtg,freeciv-client-gtk,"
            "openshot,supertuxkart,tumiki-fighters,tuxpaint,"
            "webservice-office-zoho")
        self.title_translated = _("Our star apps")
        self.published = True
        self.banner_url = "file:%s" % (os.path.abspath(os.path.join(
            softwarecenter.paths.datadir, "default_banner/fallback.png")))
        self.html = EXHIBIT_HTML % {
            'banner_url': self.banner_url,
            'title': _("Our star apps"),
            'subtitle': _("Come and explore our favourites"),
        }
        # we should extract this automatically from the html
        #self.atk_name = _("Default Banner")
        #self.atk_description = _("You see this banner because you have no "
        #    "cached banners")

class _HtmlRenderer(Gtk.OffscreenWindow):

    __gsignals__ = {
        "render-finished": (GObject.SignalFlags.RUN_LAST,
                            None,
                            (),
                           )
        }

    def __init__(self):
        Gtk.OffscreenWindow.__init__(self)
        self.view = WebKit.WebView()
        settings = self.view.get_settings()
        settings.set_property("enable-java-applet", False)
        settings.set_property("enable-plugins", False)
        settings.set_property("enable-scripts", False)
        self.view.set_size_request(-1, ExhibitBanner.MAX_HEIGHT)
        self.add(self.view)
        self.show_all()
        self.loader = SimpleFileDownloader()
        self.loader.connect("file-download-complete",
                            self.on_download_complete)
        self.loader.connect("error",
                            self.on_download_error)
        self.exhibit = None
        self.view.connect("notify::load-status", self._on_load_status)

    def _on_load_status(self, view, prop):
        if view.get_property("load-status") == WebKit.LoadStatus.FINISHED:
            # this needs to run with a timeout because otherwise the
            # status is emited before the offscreen image is finihsed
            GObject.timeout_add(100, lambda: self.emit("render-finished"))

    def on_download_error(self, loader, exception, error):
        LOG.warn("download failed: '%s', '%s'" % (exception, error))

    def on_download_complete(self, loader, path):
        image_name = os.path.basename(path)
        cache_dir = os.path.dirname(path)
        if hasattr(self.exhibit, "html") and self.exhibit.html:
            html = self.exhibit.html
        else:
            html = EXHIBIT_HTML % {
                'banner_url': self.exhibit.banner_url,
                'title': self.exhibit.title_translated,
                'subtitle': "",
            }
        # replace the server side path with the local image name, this
        # assumes that the image always comes from the same server as
        # the html
        scheme, netloc, server_path, para, query, frag = urlparse(
            self.exhibit.banner_url)
        html = html.replace(server_path, image_name)
        self.view.load_string(html, "text/html", "UTF-8",
                              "file:%s/" % cache_dir)

    def set_exhibit(self, exhibit):
        self.exhibit = exhibit
        self.loader.download_file(exhibit.banner_url,
                                  use_cache=True,
                                  simple_quoting_for_webkit=True)

class ExhibitButton(Gtk.Button):

    def __init__(self):
        Gtk.Button.__init__(self)
        self.DROPSHADOW = GdkPixbuf.Pixbuf.new_from_file(
            os.path.join(softwarecenter.paths.datadir,
                         "ui/gtk3/art/circle-dropshadow.png"))
        self.set_focus_on_click(False)
        self.set_name("exhibit-button")
        self._dropshadow = None
        # is the current active "page"
        self.is_active = False
        self.connect("size-allocate", self.on_size_allocate)

    def on_size_allocate(self, *args):
        a = self.get_allocation()
        if (self._dropshadow is not None and
            a.width == self._dropshadow.get_width() and
            a.height == self._dropshadow.get_height()):
            return

        self._dropshadow = self.DROPSHADOW.scale_simple(
                        a.width, a.width, GdkPixbuf.InterpType.BILINEAR)
        self._margin = int(float(a.width) / self.DROPSHADOW.get_width() * 15)

    def do_draw(self, cr):
        a = self.get_allocation()
        #state = self.get_state_flags()
        context = self.get_style_context()

        ds_h = self._dropshadow.get_height()
        y = (a.height - ds_h) / 2
        Gdk.cairo_set_source_pixbuf(cr, self._dropshadow, 0, y)
        cr.paint()

        # layout circle
        x = self._margin
        y = (a.height - ds_h) / 2 + self._margin
        w = a.width - 2 * self._margin
        h = a.width - 2 * self._margin
        cr.new_path()
        r = min(w, h) * 0.5
        x += int((w - 2 * r) / 2)
        y += int((h - 2 * r) / 2)
        from math import pi
        cr.arc(r + x, r + y, r, 0, 2 * pi)
        cr.close_path()

        if self.is_active:
            color = context.get_background_color(Gtk.StateFlags.SELECTED)
        else:
            color = context.get_background_color(Gtk.StateFlags.INSENSITIVE)

        Gdk.cairo_set_source_rgba(cr, color)
        cr.fill()

        for child in self:
            self.propagate_draw(child, cr)

class ExhibitArrowButton(ExhibitButton):

    def __init__(self, arrow_type, shadow_type=Gtk.ShadowType.IN):
        ExhibitButton.__init__(self)
        a = Gtk.Alignment()
        a.set_padding(1, 1, 1, 1)
        a.add(Gtk.Arrow.new(arrow_type, shadow_type))
        self.add(a)

class ExhibitBanner(Gtk.EventBox):
    # FIXME: sometimes despite set_exhibit being called the new exhibit isn't
    # actually displayed

    __gsignals__ = {
        "show-exhibits-clicked": (GObject.SignalFlags.RUN_LAST,
                                  None,
                                  (GObject.TYPE_PYOBJECT,),
                                 )
        }

    DROPSHADOW_HEIGHT = 11
    MAX_HEIGHT = 200  # pixels
    TIMEOUT_SECONDS = 10

    def __init__(self):
        Gtk.EventBox.__init__(self)
        vbox = Gtk.VBox()
        vbox.set_margin_bottom(StockEms.SMALL)
        vbox.set_margin_left(StockEms.LARGE)
        vbox.set_margin_right(StockEms.LARGE)
        self.add(vbox)

        # defined to make overriding softwarecenter.paths.datadir possible
        self.NORTHERN_DROPSHADOW = os.path.join(
            softwarecenter.paths.datadir,
            "ui/gtk3/art/exhibit-dropshadow-n.png")
        self.SOUTHERN_DROPSHADOW = os.path.join(
            softwarecenter.paths.datadir,
            "ui/gtk3/art/exhibit-dropshadow-s.png")
        self.FALLBACK = os.path.join(
            softwarecenter.paths.datadir,
            "default_banner/fallback.png")

        hbox = Gtk.HBox(spacing=StockEms.SMALL)
        vbox.pack_end(hbox, False, False, 0)

        next = ExhibitArrowButton(Gtk.ArrowType.RIGHT)
        previous = ExhibitArrowButton(Gtk.ArrowType.LEFT)
        self.nextprev_hbox = Gtk.HBox()
        self.nextprev_hbox.pack_start(previous, False, False, 0)
        self.nextprev_hbox.pack_start(next, False, False, 0)
        hbox.pack_end(self.nextprev_hbox, False, False, 0)

        self.index_hbox = Gtk.HBox(spacing=StockEms.SMALL)
        alignment = Gtk.Alignment.new(1.0, 1.0, 0.0, 1.0)
        alignment.add(self.index_hbox)
        hbox.pack_end(alignment, False, False, 0)

        self.cursor = 0
        self._timeout = 0
        self.pressed = False

        self.alpha = 1.0
        self.image = None
        self.old_image = None
        self.renderer = _HtmlRenderer()
        self.renderer.connect("render-finished", self.on_banner_rendered)

        self.set_visible_window(False)
        self.set_size_request(-1, self.MAX_HEIGHT)
        self.exhibits = []

        next.connect('clicked', self.on_next_clicked)
        previous.connect('clicked', self.on_previous_clicked)

        self._dotsigs = []

        self._cache_art_assets()
        self._init_event_handling()
        # fill this in later
        self._toplevel_window = None

    def _init_event_handling(self):
        self.set_can_focus(True)
        self.set_events(Gdk.EventMask.BUTTON_RELEASE_MASK |
                        Gdk.EventMask.BUTTON_PRESS_MASK |
                        Gdk.EventMask.ENTER_NOTIFY_MASK |
                        Gdk.EventMask.LEAVE_NOTIFY_MASK)
        self.connect("enter-notify-event", self.on_enter_notify)
        self.connect("leave-notify-event", self.on_leave_notify)
        self.connect("button-press-event", self.on_button_press)
        self.connect("button-release-event", self.on_button_release)
        self.connect("key-press-event", self.on_key_press)

    def _init_mouse_pointer(self):
        window = self.get_window()
        if not window:
            return
        if not self.exhibits[self.cursor].package_names:
            window.set_cursor(None)
        else:
            window.set_cursor(_HAND)

    def on_enter_notify(self, *args):
        self._init_mouse_pointer()

    def on_leave_notify(self, *args):
        window = self.get_window()
        window.set_cursor(None)

    def on_button_release(self, widget, event):
        if not point_in(self.get_allocation(),
                        int(event.x), int(event.y)):
            self.pressed = False
            return

        exhibit = self.exhibits[self.cursor]
        if exhibit.package_names and self.pressed:
            self.emit("show-exhibits-clicked", exhibit)
        self.pressed = False

    def on_button_press(self, widget, event):
        if point_in(self.get_allocation(),
                    int(event.x), int(event.y)):
            self.pressed = True

    def on_key_press(self, widget, event):
        # activate
        if (event.keyval == Gdk.keyval_from_name("space") or
            event.keyval == Gdk.keyval_from_name("Return") or
            event.keyval == Gdk.keyval_from_name("KP_Enter")):
            exhibit = self.exhibits[self.cursor]
            if exhibit.package_names:
                self.emit("show-exhibits-clicked", exhibit)
            return True
        # previous
        if (event.keyval == Gdk.keyval_from_name("Left") or
            event.keyval == Gdk.keyval_from_name("KP_Left")):
            self.on_previous_clicked()
            return True
        # next
        if (event.keyval == Gdk.keyval_from_name("Right") or
            event.keyval == Gdk.keyval_from_name("KP_Right")):
            self.on_next_clicked()
            return True
        return False

    def on_next_clicked(self, *args):
        self.next_exhibit()
        self.queue_next()

    def on_previous_clicked(self, *args):
        self.previous()
        self.queue_next()

    def cleanup_timeout(self):
        if self._timeout > 0:
            GObject.source_remove(self._timeout)
            self._timeout = 0

    def _render_exhibit_at_cursor(self):
        # init the mouse pointer
        self._init_mouse_pointer()
        # check the cursor is within range
        n_exhibits = len(self.exhibits)
        cursor = self.cursor
        if n_exhibits == 0 or (cursor < 0 and cursor >= n_exhibits):
            return
        # copy old image for the fade
        if self.image:
            self.old_image = self.image.copy()
        # set the rigth one
        self.renderer.set_exhibit(self.exhibits[cursor])
        # make sure the active button is having a different color
        for i, w in enumerate(self.index_hbox):
            w.is_active = (i == cursor)

    def on_paging_dot_clicked(self, dot, index):
        self.cursor = index
        self._render_exhibit_at_cursor()

    # next() is a special function in py3 so we call this next_exhibit
    def next_exhibit(self):
        if len(self.exhibits) - 1 == self.cursor:
            self.cursor = 0
        else:
            self.cursor += 1
        self._render_exhibit_at_cursor()
        return False

    def previous(self):
        if self.cursor == 0:
            self.cursor = len(self.exhibits) - 1
        else:
            self.cursor -= 1
        self._render_exhibit_at_cursor()
        return False

    def queue_next(self):
        self.cleanup_timeout()
        self._timeout = GObject.timeout_add_seconds(
                                    self.TIMEOUT_SECONDS, self.next_exhibit)
        return self._timeout

    def on_banner_rendered(self, renderer):
        self.image = renderer.get_pixbuf()

        if self.image.get_width() == 1:
            # the offscreen window is not really as such content not
            # correctly rendered
            GObject.timeout_add(500, self.on_banner_rendered, renderer)
            return

        from gi.repository import Atk
        self.get_accessible().set_name(
            self.exhibits[self.cursor].title_translated)
        self.get_accessible().set_role(Atk.Role.PUSH_BUTTON)
        self._fade_in()
        self.queue_next()
        return False

    def _fade_in(self, step=0.05):
        self.alpha = 0.0

        def fade_step():
            retval = True
            self.alpha += step

            if self.alpha >= 1.0:
                self.alpha = 1.0
                self.old_image = None
                retval = False

            self.queue_draw()
            return retval

        GObject.timeout_add(50, fade_step)

    def _cache_art_assets(self):
        global _asset_cache
        assets = _asset_cache
        if assets:
            return assets

        #~ surf = cairo.ImageSurface.create_from_png(self.NORTHERN_DROPSHADOW)
        #~ ptrn = cairo.SurfacePattern(surf)
        #~ ptrn.set_extend(cairo.EXTEND_REPEAT)
        #~ assets["n"] = ptrn

        surf = cairo.ImageSurface.create_from_png(self.SOUTHERN_DROPSHADOW)
        ptrn = cairo.SurfacePattern(surf)
        ptrn.set_extend(cairo.EXTEND_REPEAT)
        assets["s"] = ptrn
        return assets

    def do_draw(self, cr):
        # ensure that we pause the exhibits carousel if the window goes
        # into the background
        self._init_pause_handling_if_needed()

        # hide the next/prev buttons if needed
        if len(self.exhibits) == 1:
            self.nextprev_hbox.hide()
        else:
            self.nextprev_hbox.show()

        # do the actual drawing
        cr.save()

        a = self.get_allocation()

        cr.set_source_rgb(1, 1, 1)
        cr.paint()

        # workaround a really odd bug in the offscreen window of the
        # webkit view that leaves a 8px white border around the rendered
        # image
        OFFSET = -8
        if self.old_image is not None:
            #x = (a.width - self.old_image.get_width()) / 2
            x = OFFSET
            y = OFFSET
            Gdk.cairo_set_source_pixbuf(cr, self.old_image, x, y)
            cr.paint()

        if self.image is not None:
            #x = (a.width - self.image.get_width()) / 2
            x = OFFSET
            y = OFFSET
            Gdk.cairo_set_source_pixbuf(cr, self.image, x, y)
            cr.paint_with_alpha(self.alpha)

        if self.has_focus():
            # paint a focal border/frame
            context = self.get_style_context()
            context.save()
            context.add_class(Gtk.STYLE_CLASS_HIGHLIGHT)
            highlight = context.get_background_color(self.get_state_flags())
            context.restore()

            rounded_rect(cr, 1, 1, a.width - 2, a.height - 3, 5)
            Gdk.cairo_set_source_rgba(cr, highlight)
            cr.set_line_width(6)
            cr.stroke()

        # paint dropshadows last
        #~ cr.rectangle(0, 0, a.width, self.DROPSHADOW_HEIGHT)
        #~ cr.clip()
        #~ cr.set_source(assets["n"])
        #~ cr.paint()
        #~ cr.reset_clip()

        cr.rectangle(0, a.height - self.DROPSHADOW_HEIGHT,
                     a.width, self.DROPSHADOW_HEIGHT)
        cr.clip()
        cr.save()
        cr.translate(0, a.height - self.DROPSHADOW_HEIGHT)
        cr.set_source(_asset_cache["s"])
        cr.paint()
        cr.restore()

        cr.set_line_width(1)
        cr.move_to(-0.5, a.height - 0.5)
        cr.rel_line_to(a.width + 1, 0)
        cr.set_source_rgba(1, 1, 1, 0.75)
        cr.stroke()

        cr.restore()

        for child in self:
            self.propagate_draw(child, cr)

    def _init_pause_handling_if_needed(self):
        # nothing todo if we have the toplevel already
        if self._toplevel_window:
            return
        # find toplevel Gtk.Window
        w = self
        while w.get_parent():
            w = w.get_parent()
        # paranoia, should never happen
        if not isinstance(w, Gtk.Window):
            return
        # connect to property changes for the toplevel focus
        w.connect("notify::has-toplevel-focus",
                  self._on_main_window_is_active_changed)
        self._toplevel_window = w

    def _on_main_window_is_active_changed(self, win, gparamspec):
        """ this tracks focus of the main window and pauses the exhibits
            cycling if the window does not have the toplevel focus
        """
        is_active = win.get_property("has-toplevel-focus")
        if is_active:
            self.queue_next()
        else:
            self.cleanup_timeout()

    def set_exhibits(self, exhibits_list):
        if not exhibits_list:
            return

        self.exhibits = exhibits_list
        self.cursor = 0

        for child in self.index_hbox:
            child.destroy()

        for sigid in self._dotsigs:
            GObject.source_remove(sigid)

        self._dotsigs = []
        if len(self.exhibits) > 1:
            for i, exhibit in enumerate(self.exhibits):
                dot = ExhibitButton()
                dot.set_size_request(StockEms.LARGE, StockEms.LARGE)
                self._dotsigs.append(
                    dot.connect("clicked",
                                self.on_paging_dot_clicked,
                                len(self.exhibits) - 1 - i)  # index
                )
                self.index_hbox.pack_end(dot, False, False, 0)
                self.index_hbox.show_all()

        self._render_exhibit_at_cursor()

def get_test_exhibits_window():
    from mock import Mock

    win = Gtk.Window()
    win.set_size_request(600, 200)

    exhibit_banner = ExhibitBanner()

    exhibits_list = [FeaturedExhibit()]
    for (i, (title, url)) in enumerate([
        ("1 some title", "https://wiki.ubuntu.com/Brand?"
            "action=AttachFile&do=get&target=orangeubuntulogo.png"),
        ("2 another title", "https://wiki.ubuntu.com/Brand?"
            "action=AttachFile&do=get&target=blackeubuntulogo.png"),
        ("3 yet another title", "https://wiki.ubuntu.com/Brand?"
            "action=AttachFile&do=get&target=xubuntu.png"),
        ]):
        exhibit = Mock()
        exhibit.id = i
        exhibit.package_names = "apt,2vcard"
        exhibit.published = True
        exhibit.style = "some uri to html"
        exhibit.title_translated = title
        exhibit.banner_url = url
        exhibit.html = None
        exhibits_list.append(exhibit)

    exhibit_banner.set_exhibits(exhibits_list)

    scroll = Gtk.ScrolledWindow()
    scroll.add_with_viewport(exhibit_banner)
    win.add(scroll)

    win.show_all()
    win.connect("destroy", Gtk.main_quit)
    return win

if __name__ == "__main__":
    softwarecenter.paths.datadir = "./data"
    win = get_test_exhibits_window()
    Gtk.main()


import torch
from torch import nn
from src.models.encoders.charRNN import CharRNN

class CharWordEmbedding(nn.Module):
    def __init__(self, layerUtil):
        super(CharWordEmbedding, self).__init__()
        self.embedding = layerUtil.getEmbeddingParameter()
        self.charEmbedding = CharRNN(layerUtil)
        self.dropout = layerUtil.getDropOut()
        self.wordEmbedding = None
        self.eit = None

    def forward(self, wordSeqTensors, charSeqTensors, charSeqLengths):
        self.wordEmbedding = self.embedding(wordSeqTensors)
        charRNNEmbedding = self.charEmbedding(charSeqTensors, charSeqLengths)
        mergeEmbedding = torch.cat([self.wordEmbedding, charRNNEmbedding], 2)
        wordEmbeddingDropOut = self.dropout(mergeEmbedding)
        return wordEmbeddingDropOut


from transformers import AutoProcessor, AutoModel
from datasets import load_dataset
from datasets import load_dataset
import neuronperf.torch
import torch_neuron
import os
import torch
from torch import nn, tensor
from einops import repeat, rearrange

processor = AutoProcessor.from_pretrained("microsoft/layoutlmv3-base", apply_ocr=False)
model = AutoModel.from_pretrained("microsoft/layoutlmv3-base")

class NeuronCompatibilityWrapper(nn.Module):
    def __init__(self, model):
        super(NeuronCompatibilityWrapper, self).__init__()
        self.model = model

    def forward(self, encoding):
        out = self.model(input_ids = encoding['input_ids'], attention_mask = encoding['attention_mask'], bbox= encoding['bbox'], pixel_values = encoding['pixel_values'])
        return out

layout_for_trace = NeuronCompatibilityWrapper(model)

dataset = load_dataset("nielsr/funsd-layoutlmv3", split="train")
example = dataset[0]
image = example["image"]
words = example["tokens"]
boxes = example["bboxes"]

encoding = processor(image, words, boxes=boxes, return_tensors="pt")

model = model.eval()

pipeline_sizes = [1]
batch_sizes = [3, 4]

for ncp in pipeline_sizes:
    for bs in batch_sizes:
        model_file = f"layout_neuron_ncp{ncp}_bs{bs}.pt"
        encoding['input_ids'] = repeat(encoding['input_ids'], 'b h -> (x b) h', x = bs)
        encoding['bbox'] = repeat(encoding['bbox'], 'b h w -> (x b) h w', x = bs)
        encoding['pixel_values'] = repeat(encoding['pixel_values'], 'b c h w -> (x b) c h w', x = bs)
        encoding['attention_mask'] = repeat(encoding['attention_mask'], 'b w -> (x b) w', x = bs)
        for_trace_dict = {'input_ids':encoding['input_ids'], 'attention_mask':encoding['attention_mask'], 'bbox':encoding['bbox'],'pixel_values':encoding['pixel_values']}

        print(f"ncp: {ncp}  bs: {bs}")

        if not os.path.exists(model_file):
            print("Attempting model compilation")
            nmod = torch.neuron.trace(layout_for_trace, example_inputs=for_trace_dict, compiler_args=['--neuroncore-pipeline-cores', f"{ncp}"], strict=False)
            nmod.save(model_file)
            del(nmod) # we need to release the model from memory so it doesn't affect benchmarking later on
        else:
            print(f"Found previously compiled model. Skipping compilation\n")


#-*- coding: UTF-8 -*-

from PyQt5.Qt import QHBoxLayout, QGridLayout, \
    QPushButton, QLabel, QSlider, QSpinBox, QDoubleSpinBox, QImage, QPixmap, \
    QFrame, QFileDialog, QTextEdit, QRadioButton
from PyQt5 import QtCore

import os
import sys
import numpy as np
import json
import functools
from .handler import GcodeHandler

icon_path = os.path.join(os.path.split(sys.path[0])[0], 'icon')
if not os.path.exists(icon_path):
    icon_path = os.path.join(os.getcwd(), 'icon')

config_file = './config.json'
init_config = {'zeropoint_height': 0.0}

def read_config():
    error = False
    json_data = init_config
    try:
        with open(config_file, 'r') as f:
            data = f.read()
            json_data = json.loads(data)
    except Exception as e:
        print("load config error: {}".format(e))
        error = True
    if error:
        try:
            with open(config_file, 'w') as f:
                f.write(json.dumps(json_data))
        except Exception as e:
            print('write init config error: {}'.format(e))
    return json_data

def write_config(json_data):
    try:
        with open(config_file, 'w') as f:
            f.write(json.dumps(json_data))
    except Exception as e:
        print('write config error: {}: config: {}'.format(e, json_data))

class GcodeUI(object):
    def __init__(self, ui, layout):
        self.main_ui = ui
        self.layout = layout
        super(GcodeUI, self).__init__()
        self.isOutlineMode = True
        self.isLaserMode = True
        self.handler = GcodeHandler(self)
        self.set_ui()
        self.connect_slot()
        self.gcode = ''

    def set_ui(self):
        self._set_up_frame_ui()
        self._set_middle_frame_ui()
        self._set_down_frame_ui()

    def _set_up_frame_ui(self):
        self.up_frame = QFrame()
        self.up_frame.setMinimumHeight(300)
        self.up_frame.setMaximumHeight(500)
        self.up_layout = QHBoxLayout(self.up_frame)
        up_left_frame = QFrame()
        # up_left_frame.setMinimumWidth(self.main_ui.window.geometry().width() / 2)
        # up_left_frame.setMaximumWidth(self.geometry().width() / 2)
        up_right_frame = QFrame()
        # up_right_frame.setMinimumWidth(self.main_ui.window.geometry().width() / 2)
        # up_right_frame.setMaximumWidth(self.geometry().width() / 2)
        self.up_left_layout = QHBoxLayout(up_left_frame)
        self.up_right_layout = QHBoxLayout(up_right_frame)
        self.up_layout.addWidget(up_left_frame)
        # self.up_layout.addWidget(up_right_frame)
        self.layout.addWidget(self.up_frame)

        self.label_img = QLabel()
        # self.label_img.setMaximumHeight(320)
        # self.label_img.setMaximumWidth(480)
        # self.label_img.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        # self.label_img.setScaledContents(True)

        img = QImage()
        if img.load(os.path.join(icon_path, 'tmp.svg')):
            self.label_img.setPixmap(QPixmap.fromImage(img))
            with open(os.path.join(icon_path, 'tmp.svg'), 'rb') as f:
                self.handler.source = f.read()

        self.up_left_layout.addWidget(self.label_img)

        self.label_img_preview = QLabel()
        # self.label_img_preview.setMaximumHeight(320)
        # self.label_img_preview.setMaximumWidth(480)
        self.label_img_preview.setDisabled(True)
        # # self.label_img_preview.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        # # self.label_img_preview.setScaledContents(True)
        # data = np.zeros(320 * 240)
        # img = QImage(data, 320, 240, QImage.Format_RGB888)
        # pixmap = QPixmap.fromImage(img)
        # self.label_img_preview.setPixmap(pixmap)
        self.up_right_layout.addWidget(self.label_img_preview)
        # self.up_frame.hide()

    def _set_middle_frame_ui(self):
        middle_frame = QFrame()
        self.middle_layout = QHBoxLayout(middle_frame)
        middle_left_frame = QFrame()
        # middle_left_frame.setMinimumWidth(self.main_ui.window.geometry().width() / 2 - 20)
        middle_right_frame = QFrame()
        # middle_right_frame.setMinimumWidth(self.main_ui.window.geometry().width() / 2 - 20)
        self.middle_left_layout = QGridLayout(middle_left_frame)
        self.middle_right_layout = QGridLayout(middle_right_frame)

        self.middle_layout.addWidget(middle_left_frame)
        self.middle_layout.addWidget(middle_right_frame)
        self.layout.addWidget(middle_frame)

        row = 0
        self.checkbox_outline = QRadioButton('OutLine')
        self.checkbox_gray = QRadioButton('Gray')
        self.checkbox_gray.hide()
        self.btn_load_img = QPushButton('LoadImage')
        self.checkbox_outline.toggle()
        self.isOutlineMode = True
        self.checkbox_outline.setDisabled(True)
        self.middle_left_layout.addWidget(self.checkbox_outline, row, 0)
        self.middle_left_layout.addWidget(self.checkbox_gray, row, 1)
        self.middle_left_layout.addWidget(self.btn_load_img, row, 2)

        row += 1
        label_x_home = QLabel('x_home:')
        self.slider_x_home = QSlider(QtCore.Qt.Horizontal)
        self.slider_x_home.setMinimum(0)
        self.slider_x_home.setMaximum(2000)
        self.slider_x_home.setValue(1500)
        self.spinbox_x_home = QDoubleSpinBox()
        self.spinbox_x_home.setDecimals(1)
        self.spinbox_x_home.setSingleStep(0.1)
        self.spinbox_x_home.setMinimum(0.0)
        self.spinbox_x_home.setMaximum(200.0)
        self.spinbox_x_home.setValue(150.0)
        self.slider_x_home.mouseReleaseEvent = functools.partial(self.mouseReleaseEvent,
                                                                 source=self.slider_x_home.mouseReleaseEvent)
        self.spinbox_x_home.focusOutEvent = functools.partial(self.focusOutEvent,
                                                              source=self.spinbox_x_home.focusOutEvent)
        self.middle_left_layout.addWidget(label_x_home, row, 0)
        self.middle_left_layout.addWidget(self.slider_x_home, row, 1)
        self.middle_left_layout.addWidget(self.spinbox_x_home, row, 2)

        row += 1
        label_y_home = QLabel('y_home:')
        self.slider_y_home = QSlider(QtCore.Qt.Horizontal)
        self.slider_y_home.setMinimum(-1500)
        self.slider_y_home.setMaximum(1500)
        self.slider_y_home.setValue(0)
        self.spinbox_y_home = QDoubleSpinBox()
        self.spinbox_y_home.setDecimals(1)
        self.spinbox_y_home.setSingleStep(0.1)
        self.spinbox_y_home.setMinimum(-150.0)
        self.spinbox_y_home.setMaximum(150.0)
        self.spinbox_y_home.setValue(0.0)
        self.slider_y_home.mouseReleaseEvent = functools.partial(self.mouseReleaseEvent,
                                                                 source=self.slider_y_home.mouseReleaseEvent)
        self.spinbox_y_home.focusOutEvent = functools.partial(self.focusOutEvent,
                                                              source=self.spinbox_y_home.focusOutEvent)
        self.middle_left_layout.addWidget(label_y_home, row, 0)
        self.middle_left_layout.addWidget(self.slider_y_home, row, 1)
        self.middle_left_layout.addWidget(self.spinbox_y_home, row, 2)

        row += 1
        label_z_home = QLabel('z_home:')
        self.slider_z_home = QSlider(QtCore.Qt.Horizontal)
        self.slider_z_home.setMinimum(0)
        self.slider_z_home.setMaximum(1500)
        self.slider_z_home.setValue(900)
        self.spinbox_z_home = QDoubleSpinBox()
        self.spinbox_z_home.setDecimals(1)
        self.spinbox_z_home.setSingleStep(0.1)
        self.spinbox_z_home.setMinimum(0.0)
        self.spinbox_z_home.setMaximum(150.0)
        self.spinbox_z_home.setValue(90.0)
        self.slider_z_home.mouseReleaseEvent = functools.partial(self.mouseReleaseEvent,
                                                                 source=self.slider_z_home.mouseReleaseEvent)
        self.spinbox_z_home.focusOutEvent = functools.partial(self.focusOutEvent,
                                                              source=self.spinbox_z_home.focusOutEvent)
        self.middle_left_layout.addWidget(label_z_home, row, 0)
        self.middle_left_layout.addWidget(self.slider_z_home, row, 1)
        self.middle_left_layout.addWidget(self.spinbox_z_home, row, 2)

        row += 1
        label_x_offset = QLabel('x_offset:')
        self.slider_x_offset = QSlider(QtCore.Qt.Horizontal)
        self.slider_x_offset.setMinimum(-5000)
        self.slider_x_offset.setMaximum(5000)
        self.slider_x_offset.setValue(0)
        self.spinbox_x_offset = QDoubleSpinBox()
        self.spinbox_x_offset.setSingleStep(0.1)
        self.spinbox_x_offset.setDecimals(1)
        self.spinbox_x_offset.setMinimum(-500.0)
        self.spinbox_x_offset.setMaximum(500.0)
        self.spinbox_x_offset.setValue(0.0)
        self.slider_x_offset.mouseReleaseEvent = functools.partial(self.mouseReleaseEvent,
                                                                   source=self.slider_x_offset.mouseReleaseEvent)
        self.spinbox_x_offset.focusOutEvent = functools.partial(self.focusOutEvent,
                                                                source=self.spinbox_x_offset.focusOutEvent)
        self.middle_left_layout.addWidget(label_x_offset, row, 0)
        self.middle_left_layout.addWidget(self.slider_x_offset, row, 1)
        self.middle_left_layout.addWidget(self.spinbox_x_offset, row, 2)

        row += 1
        label_y_offset = QLabel('y_offset:')
        self.slider_y_offset = QSlider(QtCore.Qt.Horizontal)
        self.slider_y_offset.setMinimum(-5000)
        self.slider_y_offset.setMaximum(5000)
        self.slider_y_offset.setValue(0)
        self.spinbox_y_offset = QDoubleSpinBox()
        self.spinbox_y_offset.setDecimals(1)
        self.spinbox_y_offset.setSingleStep(0.1)
        self.spinbox_y_offset.setMinimum(-500.0)
        self.spinbox_y_offset.setMaximum(500.0)
        self.spinbox_y_offset.setValue(0.0)
        self.slider_y_offset.mouseReleaseEvent = functools.partial(self.mouseReleaseEvent,
                                                                   source=self.slider_y_offset.mouseReleaseEvent)
        self.spinbox_y_offset.focusOutEvent = functools.partial(self.focusOutEvent,
                                                                source=self.spinbox_y_offset.focusOutEvent)
        self.middle_left_layout.addWidget(label_y_offset, row, 0)
        self.middle_left_layout.addWidget(self.slider_y_offset, row, 1)
        self.middle_left_layout.addWidget(self.spinbox_y_offset, row, 2)

        row += 1
        label_z_offset = QLabel('z_offset:')
        self.slider_z_offset = QSlider(QtCore.Qt.Horizontal)
        self.slider_z_offset.setMinimum(-1000)
        self.slider_z_offset.setMaximum(1500)
        self.slider_z_offset.setValue(900)
        self.spinbox_z_offset = QDoubleSpinBox()
        self.spinbox_z_offset.setDecimals(1)
        self.spinbox_z_offset.setSingleStep(0.1)
        self.spinbox_z_offset.setMinimum(-100.0)
        self.spinbox_z_offset.setMaximum(150.0)
        self.spinbox_z_offset.setValue(90.0)
        self.slider_z_offset.mouseReleaseEvent = functools.partial(self.mouseReleaseEvent,
                                                                   source=self.slider_z_offset.mouseReleaseEvent)
        self.spinbox_z_offset.focusOutEvent = functools.partial(self.focusOutEvent,
                                                                source=self.spinbox_z_offset.focusOutEvent)
        self.middle_left_layout.addWidget(label_z_offset, row, 0)
        self.middle_left_layout.addWidget(self.slider_z_offset, row, 1)
        self.middle_left_layout.addWidget(self.spinbox_z_offset, row, 2)

        row += 1
        label_pen_up = QLabel('pen_up:')
        self.slider_pen_up = QSlider(QtCore.Qt.Horizontal)
        self.slider_pen_up.setMinimum(0)
        self.slider_pen_up.setMaximum(500)
        self.slider_pen_up.setValue(200)
        self.spinbox_pen_up = QDoubleSpinBox()
        self.spinbox_pen_up.setDecimals(1)
        self.spinbox_pen_up.setSingleStep(0.1)
        self.spinbox_pen_up.setMinimum(0.0)
        self.spinbox_pen_up.setMaximum(50.0)
        self.spinbox_pen_up.setValue(20.0)
        self.slider_pen_up.mouseReleaseEvent = functools.partial(self.mouseReleaseEvent,
                                                                 source=self.slider_pen_up.mouseReleaseEvent)
        self.spinbox_pen_up.focusOutEvent = functools.partial(self.focusOutEvent,
                                                              source=self.spinbox_pen_up.focusOutEvent)
        self.slider_pen_up.setDisabled(True)
        self.spinbox_pen_up.setDisabled(True)
        self.middle_left_layout.addWidget(label_pen_up, row, 0)
        self.middle_left_layout.addWidget(self.slider_pen_up, row, 1)
        self.middle_left_layout.addWidget(self.spinbox_pen_up, row, 2)

        row = 0
        self.checkbox_laser = QRadioButton('Laser')
        self.checkbox_pen = QRadioButton('Pen')
        self.checkbox_laser.toggle()
        self.isLaserMode = True
        self.middle_right_layout.addWidget(self.checkbox_laser, row, 0)
        self.middle_right_layout.addWidget(self.checkbox_pen, row, 1)

        row += 1
        label_drawing_feedrate = QLabel('drawing_feedrate:')
        self.slider_drawing_feedrate = QSlider(QtCore.Qt.Horizontal)
        self.slider_drawing_feedrate.setMinimum(5)
        self.slider_drawing_feedrate.setMaximum(1000)
        self.slider_drawing_feedrate.setValue(100)
        self.spinbox_drawing_feedrate = QSpinBox()
        self.spinbox_drawing_feedrate.setMinimum(5)
        self.spinbox_drawing_feedrate.setMaximum(1000)
        self.spinbox_drawing_feedrate.setValue(100)
        self.slider_drawing_feedrate.mouseReleaseEvent = functools.partial(self.mouseReleaseEvent,
                                                                           source=self.slider_drawing_feedrate.mouseReleaseEvent)
        self.spinbox_drawing_feedrate.focusOutEvent = functools.partial(self.focusOutEvent,
                                                                        source=self.spinbox_drawing_feedrate.focusOutEvent)
        self.middle_right_layout.addWidget(label_drawing_feedrate, row, 0)
        self.middle_right_layout.addWidget(self.slider_drawing_feedrate, row, 1)
        self.middle_right_layout.addWidget(self.spinbox_drawing_feedrate, row, 2)

        row += 1
        label_moving_feedrate = QLabel('moving_feedrate:')
        self.slider_moving_feedrate = QSlider(QtCore.Qt.Horizontal)
        self.slider_moving_feedrate.setMinimum(5)
        self.slider_moving_feedrate.setMaximum(20000)
        self.slider_moving_feedrate.setValue(100)
        self.spinbox_moving_feedrate = QSpinBox()
        self.spinbox_moving_feedrate.setMinimum(5)
        self.spinbox_moving_feedrate.setMaximum(20000)
        self.spinbox_moving_feedrate.setValue(100)
        self.slider_moving_feedrate.mouseReleaseEvent = functools.partial(self.mouseReleaseEvent,
                                                                          source=self.slider_moving_feedrate.mouseReleaseEvent)
        self.spinbox_moving_feedrate.focusOutEvent = functools.partial(self.focusOutEvent,
                                                                       source=self.spinbox_moving_feedrate.focusOutEvent)
        self.middle_right_layout.addWidget(label_moving_feedrate, row, 0)
        self.middle_right_layout.addWidget(self.slider_moving_feedrate, row, 1)
        self.middle_right_layout.addWidget(self.spinbox_moving_feedrate, row, 2)

        row += 1
        label_scale = QLabel('scale:')
        self.slider_scale = QSlider(QtCore.Qt.Horizontal)
        self.slider_scale.setMinimum(1)
        self.slider_scale.setMaximum(100)
        self.slider_scale.setValue(10)
        self.spinbox_scale = QDoubleSpinBox()
        self.spinbox_scale.setDecimals(1)
        self.spinbox_scale.setSingleStep(0.1)
        self.spinbox_scale.setMinimum(0.1)
        self.spinbox_scale.setMaximum(10.0)
        self.spinbox_scale.setValue(1.0)
        # self.slider_scale.setDisabled(True)
        # self.spinbox_scale.setDisabled(True)
        self.slider_scale.mouseReleaseEvent = functools.partial(self.mouseReleaseEvent,
                                                                source=self.slider_scale.mouseReleaseEvent)
        self.spinbox_scale.focusOutEvent = functools.partial(self.focusOutEvent,
                                                             source=self.spinbox_scale.focusOutEvent)

        self.middle_right_layout.addWidget(label_scale, row, 0)
        self.middle_right_layout.addWidget(self.slider_scale, row, 1)
        self.middle_right_layout.addWidget(self.spinbox_scale, row, 2)

        row += 1
        label_resolution = QLabel('resolution:')
        self.slider_resolution = QSlider(QtCore.Qt.Horizontal)
        self.slider_resolution.setMinimum(1)
        self.slider_resolution.setMaximum(100)
        self.slider_resolution.setValue(10)
        self.spinbox_resolution = QDoubleSpinBox()
        self.spinbox_resolution.setMinimum(0.1)
        self.spinbox_resolution.setMaximum(10.0)
        self.spinbox_resolution.setSingleStep(0.1)
        self.spinbox_resolution.setDecimals(1)
        self.spinbox_resolution.setValue(1.0)
        self.slider_resolution.setDisabled(True)
        self.spinbox_resolution.setDisabled(True)
        self.middle_right_layout.addWidget(label_resolution, row, 0)
        self.middle_right_layout.addWidget(self.slider_resolution, row, 1)
        self.middle_right_layout.addWidget(self.spinbox_resolution, row, 2)

        row += 1
        self.btn_generate_gcode = QPushButton('Generate_Gcode')
        self.middle_right_layout.addWidget(self.btn_generate_gcode, row, 0)

        row += 1
        self.label_x_min = QLabel('')
        self.label_x_max = QLabel('')
        self.middle_right_layout.addWidget(self.label_x_min, row, 0)
        self.middle_right_layout.addWidget(self.label_x_max, row, 1)

        row += 1
        self.label_y_min = QLabel('')
        self.label_y_max = QLabel('')
        self.middle_right_layout.addWidget(self.label_y_min, row, 0)
        self.middle_right_layout.addWidget(self.label_y_max, row, 1)

    def _set_down_frame_ui(self):
        self.down_frame = QFrame()
        self.down_layout = QHBoxLayout(self.down_frame)
        self.layout.addWidget(self.down_frame)

        self.textEdit = QTextEdit()
        self.down_layout.addWidget(self.textEdit)
        # self.down_frame.hide()

    def select_engrave_mode(self, event):
        self.isOutlineMode = event
        # print('outline: {}, laser: {}'.format(self.isOutlineMode, self.isLaserMode))

    def select_end_type(self, event):
        self.isLaserMode = event
        self.slider_pen_up.setDisabled(self.isLaserMode)
        self.spinbox_pen_up.setDisabled(self.isLaserMode)
        self.generate_gcode()
        # print('outline: {}, laser: {}'.format(self.isOutlineMode, self.isLaserMode))

    def connect_slot(self):
        self.checkbox_outline.toggled.connect(self.select_engrave_mode)
        self.checkbox_laser.toggled.connect(self.select_end_type)
        self.btn_load_img.clicked.connect(self.load_image)

        self.slider_x_home.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.spinbox_x_home, scale=.1))
        self.spinbox_x_home.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.slider_x_home, scale=10))

        self.slider_y_home.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.spinbox_y_home, scale=.1))
        self.spinbox_y_home.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.slider_y_home, scale=10))

        self.slider_z_home.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.spinbox_z_home, scale=.1))
        self.spinbox_z_home.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.slider_z_home, scale=10))

        self.slider_x_offset.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.spinbox_x_offset, scale=.1))
        self.spinbox_x_offset.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.slider_x_offset, scale=10))

        self.slider_y_offset.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.spinbox_y_offset, scale=.1))
        self.spinbox_y_offset.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.slider_y_offset, scale=10))

        self.slider_z_offset.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.spinbox_z_offset, scale=.1))
        self.spinbox_z_offset.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.slider_z_offset, scale=10))

        self.slider_pen_up.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.spinbox_pen_up, scale=.1))
        self.spinbox_pen_up.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.slider_pen_up, scale=10))

        self.slider_scale.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.spinbox_scale, scale=.1))
        self.spinbox_scale.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.slider_scale, scale=10))

        self.slider_resolution.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.spinbox_resolution, scale=.1))
        self.spinbox_resolution.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.slider_resolution, scale=10))

        self.slider_drawing_feedrate.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.spinbox_drawing_feedrate, scale=1))
        self.spinbox_drawing_feedrate.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.slider_drawing_feedrate, scale=1))

        self.slider_moving_feedrate.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.spinbox_moving_feedrate, scale=1))
        self.spinbox_moving_feedrate.valueChanged.connect(
            functools.partial(self.slider_spinbox_related, slave=self.slider_moving_feedrate, scale=1))

        self.btn_generate_gcode.clicked.connect(functools.partial(self.generate_gcode, flag=True))

    def slider_spinbox_related(self, value, master=None, slave=None, scale=1):
        try:
            slave.setValue(value * scale)
        except Exception as e:
            print(e)

    def mouseReleaseEvent(self, event, source=None):
        try:
            self.generate_gcode()
        except Exception as e:
            print(e)
        source(event)

    def focusOutEvent(self, event, source=None):
        try:
            self.generate_gcode()
        except Exception as e:
            print(e)
        source(event)

    def generate_gcode(self, flag=False):
        if self.handler.template is None and flag:
            self.handler.svg_to_gcode()
        if self.handler.template:
            pen_up = self.spinbox_pen_up.value() if not self.isLaserMode else 0
            config = {
                'x_home': self.spinbox_x_home.value(),
                'y_home': self.spinbox_y_home.value(),
                'z_home': self.spinbox_z_home.value(),
                'z_offset': self.spinbox_z_offset.value(),
                'pen_up': pen_up,
                'z_offset_pen_up': self.spinbox_z_offset.value() + pen_up,
                'moving_feedrate': self.spinbox_moving_feedrate.value(),
                'drawing_feedrate': self.spinbox_drawing_feedrate.value(),
            }
            self.gcode = self.handler.template.format(**config)
            self.change_gcode()
            # self.textEdit.setText(self.gcode)

    def change_gcode(self):
        if self.gcode:
            x_offset = self.spinbox_x_offset.value()
            y_offset = self.spinbox_y_offset.value()
            z_offset = self.spinbox_z_offset.value()
            moving_feedrate = self.spinbox_moving_feedrate.value()
            drawing_feedrate = self.spinbox_drawing_feedrate.value()
            scale = self.spinbox_scale.value()

            lines = self.gcode.split('\n')
            for i, line in enumerate(lines):
                List = line.strip().split(' ')
                line = ''
                for l in List:
                    if l.startswith('F'):
                        if line.startswith(('G01', 'G1')):
                            l = 'F{}'.format(drawing_feedrate)
                        elif line.startswith(('G00', 'G0')):
                            l = 'F{}'.format(moving_feedrate)
                    elif l.startswith('X'):
                        x = float(l[1:]) * scale + x_offset
                        l = 'X{0:.2f}'.format(x)
                    elif l.startswith('Y'):
                        y = float(l[1:]) * scale + y_offset
                        l = 'Y{0:.2f}'.format(y)
                    # elif l.startswith('Z'):
                    #     z = float(l[1:]) + z_offset
                    #     l = 'Z{0:.2f}'.format(z)
                    line += l + ' '
                line = line.strip()
                lines[i] = line
            self.calc_gcode(lines)
            gcode = '\n'.join(lines)
            self.textEdit.setText(gcode)

    def calc_gcode(self, lines):
        x_list = []
        y_list = []
        for i, line in enumerate(lines):
            if line.startswith(tuple(['G0', 'G1', 'G00', 'G01'])):
                List = line.strip().split(' ')
                for l in List:
                    if l.startswith('X'):
                        x = float(l[1:])
                        x_list.append(x)
                    elif l.startswith('Y'):
                        y = float(l[1:])
                        y_list.append(y)
        if len(x_list) > 0:
            x_min = np.min(x_list)
            x_max = np.max(x_list)
            self.label_x_min.setText('X(min): ' + str(x_min))
            self.label_x_max.setText('X(max): ' + str(x_max))
            # print('x_min: {}, x_max: {}, x_distance: {}'.format(x_min, x_max, x_max - x_min))
        if len(y_list) > 0:
            y_min = np.min(y_list)
            y_max = np.max(y_list)
            self.label_y_min.setText('Y(min): ' + str(y_min))
            self.label_y_max.setText('Y(max): ' + str(y_max))
            # print('y_min: {}, y_max: {}, y_distance: {}'.format(y_min, y_max, y_max - y_min))

    def load_image(self):
        fname = QFileDialog.getOpenFileName(self.main_ui.window, 'Open file', '', '*.svg')
        if fname and fname[0]:
            img = QImage()
            if img.load(fname[0]):
                self.label_img.setPixmap(QPixmap.fromImage(img))
                with open(fname[0], 'rb') as f:
                    self.handler.source = f.read()
                    self.handler.template = None
                    self.gcode = None
                    self.up_frame.show()


# -*- coding: utf-8 -*-
from flask import abort, request
from flask_restful import Resource
from py_app.models.mod1_ativos import ComplexoMinerario, Estrutura, AssocAtivoComplexo, Ativo, Manutencao
from py_app.blueprints.rest_api.utils import http_messages

from datetime import datetime

from py_app.extensions.database import db

import pika
from dynaconf import settings
from json import dumps

class MiningComplexResource(Resource):
    def get(self):
        return list_mining_complex()

    def post(self):
        try:
            r = request.json

            mining_complex = ComplexoMinerario(
              nome=r['nome'].title() if r['nome'] else None,
              lat=r['lat_long'][0],
              long=r['lat_long'][1],
              uf=r['uf'],
              municipio=r['municipio'],
              situacao_operacional=r['situacao_operacional'],
            )

            for s in r['estruturas']:
                structure = Estrutura(
                    tipo=s['tipo'],
                    descricao=s['descricao'].title() if s['descricao'] else None,
                    inserida_pnsb=s['inserida_pnsb'],
                    dpa=s['dpa'],
                    cri=s['cri'],
                    paemb_url=s['paemb_url'],
                    nivel_emergencia=s['nivel_emergencia'],
                    situacao_operacional=s['situacao_operacional']
                )
                mining_complex.estruturas.append(structure)

            for a in r['ativos']:
                quantity = a['qt']
                asset_id = a['assetId']
                asset_to_update = Ativo.query.get(asset_id);
                if asset_to_update.quantidade < quantity:
                    return http_messages.http_message(400, f'{asset_to_update.descricao} (ID {asset_to_update.id}) não possui quantidade suficiente.')
                asset_to_update.quantidade -= quantity
                asset = AssocAtivoComplexo(
                    ativo_id=asset_id,
                    quantidade=quantity
                )
                mining_complex.assoc_ativo_complexos.append(asset)

            db.session.add(mining_complex)
            db.session.commit()
            db.session.refresh(mining_complex)

            send_info_to_queue({
                'id': mining_complex.id,
                'nome': mining_complex.nome,
                'situacao_operacional': mining_complex.situacao_operacional
            })

            return http_messages.http_message(201, 'Created', mining_complex.id)
        except Exception as e:
            print(e)
            return http_messages.bad_request(e)

class MiningComplexItemResource(Resource):
    def get(self, mining_complex_id):
        return list_mining_complex(mining_complex_id)

    def put(self):
        pass

    def delete(self):
        pass

class MiningComplexScheduleResource(Resource):
    def get(self, mining_complex_id):
        try:
            mining_complex = ComplexoMinerario.query.filter_by(id=mining_complex_id).first()
            if not mining_complex:
                return http_messages.not_found()
            return mining_complex.to_dict(complete=True, schedule=True), 200
        except Exception as e:
            return http_messages.internal_error(e)

    def post(self, mining_complex_id):
        try:
            r = request.json
            start_date = datetime.strptime(r['data_hora'], '%Y-%m-%dT%H:%M')
            if start_date < datetime.now():
                return http_messages.http_message(400, 'O evento não pode ser marcado para um período passado.')

            end_date = datetime.strptime(r['conclusao'], '%Y-%m-%dT%H:%M') if r['conclusao'] else None
            if end_date and end_date < start_date:
                return http_messages.http_message(400, 'A data final não pode ser anterior à data inicial.')

            description = r['descricao'].title() if r['descricao'] else None
            asset_id = r['ativo_id']
            if r['id']:
                maintenance = Manutencao.query.get(r['id'])
                if not maintenance:
                    return http_messages.bad_request()
                maintenance.descricao = description
                maintenance.data_hora = start_date
                maintenance.conclusao = end_date
                maintenance.ativo_id = asset_id
            else:
                maintenance = Manutencao(
                    descricao=description,
                    data_hora=start_date,
                    conclusao=end_date,
                    ativo_id=asset_id,
                    complexo_minerario_id=mining_complex_id
                )
                db.session.add(maintenance)
            db.session.commit()
            return http_messages.http_message(200, 'OK')
        except Exception as e:
            print(e)
            return http_messages.bad_request(e)

class MiningComplexEquipmentsResource(Resource):
    def patch(self):
        try:
            r = request.json
            asset_id = r['assetId']
            update_quantity = r['qt']
            mining_complex_id = r['miningComplexId']

            asset_to_update = Ativo.query.get(asset_id);
            asset = AssocAtivoComplexo.query.filter_by(
                complexo_minerario_id=mining_complex_id,
                ativo_id=asset_id
            ).first()
            if asset:
                if update_quantity == 0:
                    asset_to_update.quantidade += asset.quantidade
                    db.session.delete(asset)
                elif update_quantity > asset.ativo.quantidade:
                    return http_messages.http_message(400, f'{asset_to_update.descricao} (ID {asset_to_update.id}) não possui quantidade suficiente.')
                else:
                    asset_to_update.quantidade += asset.quantidade
                    asset.quantidade = update_quantity
                    asset_to_update.quantidade -= update_quantity
            else:
                asset = AssocAtivoComplexo(
                    complexo_minerario_id=mining_complex_id,
                    ativo_id=asset_id,
                    quantidade=update_quantity
                )
                db.session.add(asset)
            db.session.commit()
            return http_messages.http_message(200, 'OK')
        except Exception as e:
            print(e)
            return http_messages.bad_request(e)

class MiningComplexStructuresResource(Resource):

    def post(self):
        try:
            r = request.json

            structure = Estrutura(
                tipo=r['tipo'],
                descricao=r['descricao'].title() if r['descricao'] else None,
                inserida_pnsb=r['inserida_pnsb'],
                dpa=r['dpa'],
                cri=r['cri'],
                paemb_url=r['paemb_url'],
                nivel_emergencia=r['nivel_emergencia'],
                situacao_operacional=r['situacao_operacional'],
                complexo_minerario_id=r['complexo_minerario_id']
            )

            db.session.add(structure)
            db.session.commit()
            db.session.refresh(structure)
            return http_messages.http_message(201, 'Created', structure.id)
        except Exception as e:
          return http_messages.bad_request(e)

    def patch(self):
        try:
            r = request.json

            structure_to_update = Estrutura.query.get(r['id'])

            if structure_to_update:
                structure_to_update.tipo = r['tipo']
                structure_to_update.descricao = r['descricao'].title() if r['descricao'] else None,
                structure_to_update.inserida_pnsb = r['inserida_pnsb']
                structure_to_update.dpa = r['dpa']
                structure_to_update.cri = r['cri']
                structure_to_update.paemb_url = r['paemb_url']
                structure_to_update.nivel_emergencia = r['nivel_emergencia']
                structure_to_update.situacao_operacional = r['situacao_operacional']

                db.session.commit()
                return http_messages.http_message(200, 'OK')
            return http_messages.not_found()
        except Exception as e:
            return http_messages.bad_request(e)

def list_mining_complex(id=None):
    try:
        if id:
            mining_complex = ComplexoMinerario.query.filter_by(id=id).first()
            if not mining_complex:
                return http_messages.not_found()
            return_data = mining_complex.to_dict(complete=True)
        else:
            mining_complexes = ComplexoMinerario.query.all()
            return_data = {
                'count': len(mining_complexes),
                'next': None,
                'previous': None,
                'results': [mining_complex.to_dict() for mining_complex in mining_complexes]
            }
        return return_data, 200
    except Exception as e:
        return http_messages.internal_error(e)

def send_info_to_queue(data):
    try:
        connection = pika.BlockingConnection(
            pika.URLParameters(settings.RABBITMQ_URI)
        )
        data_dumps = dumps(data)

        channel = connection.channel()

        channel.queue_declare(queue='mining-complex-queue', durable=True)

        channel.basic_publish(
            exchange='amq.direct',
            routing_key='mining_complex_rk',
            body=data_dumps
        )
        print(f" [x] Enviando dados para a fila... {data_dumps}")
        connection.close()
    except Exception as e:
        print('Dados não enviados para a fila.')
        print(e)