import time
from logging import getLogger

import six
from constance import config
from django.conf import settings
from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse
from django.utils.crypto import constant_time_compare, salted_hmac
from django.utils.http import base36_to_int, int_to_base36
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from sentry_sdk import capture_exception
from viberbot import Api, BotConfiguration
from viberbot.api.messages import TextMessage
from viberbot.api.viber_requests import (ViberMessageRequest,
                                         ViberSubscribedRequest,
                                         ViberUnsubscribedRequest,)

from bitcaster.api.fields import PasswordField, PhoneNumberField
from bitcaster.exceptions import PluginSendError
from bitcaster.otp import OtpHandler
from bitcaster.utils.http import absolute_uri
from bitcaster.utils.reflect import fqn

from ..base import (CoreDispatcher, DispatcherOptions,
                    MessageType, SubscriptionOptions,)
from ..registry import dispatcher_registry

logger = getLogger(__name__)

class ViberMessage(MessageType):
    has_subject = False
    allow_html = False

class ViberSubscription(SubscriptionOptions):
    recipient = PhoneNumberField()

class ViberOptions(DispatcherOptions):
    account_name = serializers.CharField(help_text=_('Account Name'))
    uri = serializers.CharField(help_text=_('Uri'))
    # site = serializers.URLField(help_text=_('This server url.'),
    #                             initial=lambda: state.request.build_absolute_uri('/'))
    avatar = serializers.URLField(help_text=_('Account Image'),
                                  required=False, allow_blank=True)
    auth_token = PasswordField()

@dispatcher_registry.register
class Viber(CoreDispatcher):
    options_class = ViberOptions
    subscription_class = ViberSubscription
    message_class = ViberMessage
    need_verification = False
    icon = 'viber.png'
    __help__ = _("""Viber dispatcher to send private message

#### Get API keys

* Register at [[https://partners.viber.com/about]]
* Click on [Create Bot Account](https://partners.viber.com/account/create-bot-account)
* Copy the token and paste it here""")

    def get_usage(self) -> object:
        info = {'qrcode': 'viber://pa/info?uri=%s' % self.config['uri'],
                'url': reverse('qrcode')}
        info.update(self.config)
        return _("""
* Open your Viber application and goto More->QR code
* Scan the following code

* On the top-right open the popup menu and select **Receive messages**
* Check your chat and click on the link you have just received
* That's all. Now you are ready to receive messages.
""") % dict(info)

    def _make_token_with_timestamp(self, user):
        ts_b36 = int_to_base36(int(time.time()))

        hash = salted_hmac(
            settings.SECRET_KEY,
            six.text_type(user.id) + six.text_type(ts_b36)
        ).hexdigest()[::2]
        return '%s-%s' % (ts_b36, hash)

    def check_token(self, user, token):
        """
        Check that a password reset token is correct for a given user.
        """
        if not (user and token):
            return False
        # Parse the token
        try:
            ts_b36, hash = token.split('-')
        except ValueError:
            return False

        try:
            ts = base36_to_int(ts_b36)
        except ValueError:
            return False

        # Check that the timestamp/uid has not been tampered with
        if not constant_time_compare(self._make_token_with_timestamp(user, ts), token):
            return False

        # Check the timestamp is within limit. Timestamps are rounded to
        # midnight (server time) providing a resolution of only 1 day. If a
        # link is generated 5 minutes before midnight and used 6 minutes later,
        # that counts as 1 day. Therefore, PASSWORD_RESET_TIMEOUT_DAYS = 1 means
        # "at least 1 day, could be up to 2."
        if (self._num_days(self._today()) - ts) > 1:  # greater than 1 day
            return False

        return True

    def _get_connection(self) -> Api:
        config = self.config

        bot_configuration = BotConfiguration(
            name=config['account_name'],
            avatar=config['avatar'],
            auth_token=config['auth_token'],
        )
        return Api(bot_configuration)

    def registration(self, request):
        otp = request.GET.get('otp')
        messages, dt = OtpHandler().validate(otp)
        request.user.store(fqn(self), self.owner.pk, messages[0])
        assignment = request.user.assignments.get(channel=self.owner)
        assignment.verified = True
        assignment.save()
        return HttpResponseRedirect('/')

    def callback(self, request):
        conn = self._get_connection()
        if not conn.verify_signature(request.body, request.META.get('X-Viber-Content-Signature')):
            logger.error('Viber 403: %s' % request.body)
        viber_request = conn.parse_request(request.body)

        if isinstance(viber_request, ViberUnsubscribedRequest):
            # viber_request.event_type == "unsubscribed"
            # viber_request.timestamp == int: milliseconds since epoch , eg 1554674273997
            # viber_request.user_id == str ... eg "qc7TSxYS+jiMst8pEYI56w=="
            try:
                # TODO: very inefficient way of retrieving the user
                from bitcaster.models import User
                user = None
                for u in User.objects.all():
                    if u.storage and u.retrieve(fqn(self), self.owner.pk) == viber_request.user_id:
                        user = u
                        break
                if user:
                    user.store(fqn(self), self.owner.pk, None)
            except Exception as e:
                capture_exception()
                logger.exception(e)
        elif isinstance(viber_request, ViberSubscribedRequest):
            otp = OtpHandler().get_otp(str(viber_request.user.id))
            url = absolute_uri(reverse('channel-registration', args=[self.owner.pk]))
            message = TextMessage(text='%s?otp=%s' % (url, otp.decode()))
            conn.send_messages(viber_request.user.id, [message])
            return HttpResponse()
        elif isinstance(viber_request, ViberMessageRequest):
            message = viber_request.message
            conn.send_messages(viber_request.sender.id, [message])
        return HttpResponse()

    def get_recipient_address(self, subscription):
        if isinstance(subscription, str):
            raise ValueError(subscription)
        if hasattr(subscription, 'subscriber'):  # models.Subscription
            user = subscription.subscriber
        elif hasattr(subscription, 'assignments'):  # models.User
            user = subscription
        else:
            raise ValueError()
        return user.retrieve(fqn(self), self.owner.pk)
        # return user.assignments.get_address(self).address

    def emit(self, address: str, subject, message, connection=None, *args, **kwargs) -> str:
        try:
            conn = connection or self._get_connection()
            url = reverse('channel-callback', args=[self.owner.pk])
            cb = '%s%s' % (config.SITE_URL, url)
            conn.set_webhook(cb)

            text_message = TextMessage(text=message)
            conn.send_messages(address, text_message)
            self.logger.debug(f'{fqn(self)} sent to {address}')
            return address
        except Exception as e:
            raise PluginSendError(e)

    def test_connection(self, raise_exception=False) -> bool:
        try:
            self._get_connection()
            return True
        except Exception as e:
            self.logger.exception(e)
            if raise_exception:
                raise
            return False


def sumDigits(t):
    t = t.replace(".", "")
    return sum(map(int, t))

def sumClock(pair):
    total = 0
    return sumDigits(pair[0]) + sumDigits(pair[1])

def timeDiff(t, d):
    m, s = map(int, t.split("."))
    s -= d
    if s < 0:
        m -= 1
        s += 60
    return "{}.{:02d}".format(m, s)

def chessClockSumOfDigits(initialTime, k):
    # some int error
    minTime1 = 9999
    maxTime1 = 0
    minTime2 = 9999
    maxTime2 = 0
    t1 = initialTime[0]
    t2 = initialTime[1]
    for s in range(k+1):
        t1d = s
        t2d = k - s
        newT1 = timeDiff(t1, t1d)
        newT2 = timeDiff(t2, t2d)
        curSum1 = sumDigits(newT1)

        if curSum1 > maxTime1:
            maxTime1 = curSum1
        if curSum1 < minTime1:
            minTime1 = curSum1
        for t in range(k+1-s):
            t2d = t
            newT2 = timeDiff(t2, t2d)
            curSum2 = sumDigits(newT2)

            if curSum2 > maxTime2:
                maxTime2 = curSum2
            if curSum2 < minTime2:
                minTime2 = curSum2

    return [minTime1 + minTime2, maxTime1 + maxTime2]

def test():
    testeql(chessClockSumOfDigits(["3.05", "9.02"], 9), [12, 38])
    # testeql(sumDigits("1.02"), 3)
    # testeql(timeDiff("3.00", 1), "2.59")


from rab import create_url
import requests
import citylocs
import folium
import os
import time

from pathlib import Path

from selenium import webdriver
from html.parser import HTMLParser
import imageio

def get_all_baptisms(name):
    values = {
        'vrij_tekst': '',
        'vrij_periode': '',
        'vrij_plaats': '',
        'pers1_voornaam':'',
        'pers1_achternaam':name,
        'pers2_voornaam': '',
        'pers2_achternaam': '',
        'pers1_beroep':'',
        'pers1_rol':'Dopeling',
        'pers2_rol': '',
        'akteperiode': '',
        'zw_m' : '0',
        'zw_v' : '0',
        'zw_o' : '0',
        'matchtype': 'Exact'
    }

    url = create_url(values)
    print(url)
    r = requests.get(url)

    results = []

    for role in ['Dopeling', 'Kind']:
        values['pers1_rol'] = role
        startrecord = 0

        while startrecord is not None:
            url = create_url(values, startrecord=startrecord)
            print(url)
            r = requests.get(url)
            parser = PersonResultsParser(results)
            parser.feed(r.text)
            startrecord = parser.next_record()

    print(len(results))
    return results

def bucketize_by_decade(entries):
    #['BOVEKERKE', (51.0542624, 2.9634051), '16-10-1799', 'Coleta Sophia']
    buckets = {}
    buckets[0] = []
    for e in entries:
        if e[2] != '' and e[2] is not None:
            y = 0
            if '-' in e[2]:
                d = str(e[2])
                y = d.split('-')[2]
            elif '/' in e[2]:
                y = e[2].split('/')
                y = y[-1]
            else:
                y = e[2]
            decade = round(int(y) / 10 - .5)
            if decade not in buckets.keys():
                buckets[decade] = []
            buckets[decade].append(e)
        else:
            buckets[0].append(e)
    return buckets

def create_animation(name, decade_buckets, create_gif = False):
    maps = []
    place, centre = citylocs.get_city_location("WALHAIN")

    for dec, entries in decade_buckets.items():
        if dec != 0:
            m = folium.Map(location=centre, zoom_start=8, width=1024, height=620)
            m.png_enabled
            for e in entries:
                location = e[1]
                marker = folium.Marker(location,
                    popup="",
                    tooltip=""
                )
                marker.add_to(m)
            fname = str(dec)
            title_html = '''

{}

                         '''.format('Geboortes (PR/BS) familie '+name + ' jaren: ' + str(dec*10) + "-" + str(dec*10+9))
            m.get_root().html.add_child(folium.Element(title_html))
            maps.append((dec, m._repr_html_()))
            if create_gif:
                m.save(fname+".html")
                tmpurl = 'file://{path}/{mapfile}.html'.format(path=os.getcwd(), mapfile=fname)

                browser = webdriver.Chrome()
                browser.set_window_size(1100, 850)
                browser.get(tmpurl)

                # Give the map tiles some time to load
                time.sleep(2)
                browser.save_screenshot(fname + '.png')
                browser.quit()

                #image = Image.open(fname + '.png')
                #box = (0, 0, 1024, 620)
                #cropped_image = image.crop(box)
                #cropped_image.save('total_perYear_' + str(i) + '.png')

                os.remove(fname+".html")

    if create_gif:
        image_path = Path()

        images = list(image_path.glob('*.png'))
        image_list = []
        for file_name in images:
            image_list.append(imageio.imread(file_name))
            os.remove(file_name)

        imageio.mimwrite('GifMap.gif', image_list, fps=1)
    return maps

def geolocate(entries):
    r=[]
    notfound=[]
    for e in entries:
        (name, location) = citylocs.get_city_location(e[1].upper())
        l = ''
        if location != (0,0):
            l = [name, location, e[2],e[4]]
            r.append(l)
        else:
            notfound.append(l)
    return r, notfound

class PersonDetailsParser(HTMLParser):
    def __init__(self):
        HTMLParser.__init__(self)
        self.expect_data = False
        self.year = None
    def handle_starttag(self, tag, attrs):
        if tag == 'td':
            self.expect_data = True
        return
    def handle_endtag(self, tag):
        if tag == 'td':
            self.expect_data = False
        return
    def handle_data(self, data):
        if self.expect_data:
            data = data.strip()
            if data.startswith('(') and data.endswith(')'):
                self.year = data.strip('()')
        return

class PersonResultsParser(HTMLParser):
    def __init__(self, results):
        HTMLParser.__init__(self)
        self.__inbody = False;
        self.__currentrow = []
        self.__addrowdata = False;
        self.__rowdata = ''
        self.__expectcounterdata = False
        self.__results = results
        self.__recordtotal = 0
        self.__recordend = False
        self.__recordfinal = False

    def handle_starttag(self, tag, attrs):
        self.__expectcounterdata = False
        if tag == 'div' and attrs == [('class', 'resultscounter')]:
            self.__expectcounterdata = True
        if tag == 'tbody':
            self.__inbody = True
        if tag == 'tr'  and self.__inbody:
            self.__inrow= True
            self.__currentrow = []
        if tag == 'td' and self.__inbody :
            self.__rowdata = ''
            if len(attrs) == 0:
                self.__addrowdata = True
            elif attrs == [('class', 'nowrap')]:
                self.__addrowdata = True
        if tag == 'a' and self.__inbody:
            appendhref = False
            for key, value in attrs:
                if (key, value) == ('class', 'modal'):
                    appendhref = True
                if appendhref and key == 'href':
                    self.__currentrow.append(value)
                    appendhref = False;

    def handle_endtag(self, tag):
        if tag == 'div':
            self.__expectcounterdata = False
        if tag == 'tbody':
            self.__inbody = False
        if tag == 'tr' and self.__inbody:
            if self.__currentrow[2] == '':
                url = "https://search.arch.be/" + self.__currentrow[6]
                print(url)
                r = requests.get(url)
                p = PersonDetailsParser()
                p.feed(r.text)
                self.__currentrow[2] = p.year

            self.__results.append(self.__currentrow)
            self.__inrow = False
        if tag == 'td' and self.__inbody:
            self.__addrowdata = False
            self.__currentrow.append(self.__rowdata)
        return

    def handle_data(self, data):
        if self.__expectcounterdata is True:
            data = data.split()
            self.__recordtotal =  data[5]
            self.__recordend = data[3]
            self.__recordfinal = (data[3] == self.__recordtotal)
        if self.__addrowdata:
            self.__rowdata = data

    def next_record(self):
        if self.__recordfinal :
            return None
        return self.__recordend

name = 'Velle'
results = get_all_baptisms(name)
print(results[1])

geolocated, notfound = geolocate(results)

print('entries without location :'+ str(len(notfound)))
print(geolocated)
decade_buckets = bucketize_by_decade(geolocated)
print('entries without date :'+ str(len(decade_buckets[0])))
create_animation(name, decade_buckets, create_gif=True)


"""
Apple iBooks annotations. Read the iBooks' annotations database using
https://github.com/jussihuotari/pinotate

I wonder if it would be possible to extract reading progress events from the
database, similar to https://github.com/karlicoss/kobuddy
"""
REQUIRES = ['pinotate']

from my.config import ibooks as config # type: ignore[attr-defined]
from pinotate.core import IBooksWorker # type: ignore
from datetime import datetime, timedelta
from pathlib import Path
from typing import Iterator, NamedTuple, Optional, List

# Typed copy of https://github.com/jussihuotari/pinotate/blob/master/core/highlight.py
class Highlight(NamedTuple):
    text: str
    heading: str
    created: datetime
    chapter: int
    ref_in_chapter: int

class Book(NamedTuple):
    author: str
    title: str
    highlights: List[Highlight]

def _parse_date(seconds_since_ref_date: int) -> datetime:
    reference_date = datetime(2001, 1, 1, 0, 0, 0)
    delta_since_reference = timedelta(seconds=seconds_since_ref_date)
    utc = (reference_date + delta_since_reference)
    return utc

def _iter_books() -> Iterator[Book]:
    worker = IBooksWorker()
    for (author, title) in worker.titles():
        aid = worker.asset_id(title)
        data = worker.highlights(aid)
        #print(f"Processing book '{title}', {aid}.")
        highlights = [Highlight(d.text, d.heading, _parse_date(d.created), d.chapter, d.ref_in_chapter) for d in data]
        if len(highlights):
            yield Book(author = author, title = title, highlights = highlights)

def books() -> List[Book]:
    return list(sorted(_iter_books(), key=lambda b: (b.author, b.title)))


import sys
from collections import deque
import time

sys.stdout = open('text.txt','w')
sys.stdin = open('int.txt','r')

def singleRemaining(men_eng):
    if -1 in men_eng:
        return True
    else:
        return False

T = int(input())
while (T):
    N = int(input())
    men_prf = []
    women_prf = []
    for i in range(N):
        incoming = deque(map(int,input().strip().split()))
        incoming.popleft()
        women_prf.append(incoming)
    for i in range(N):
        incoming = deque(map(int,input().strip().split()))
        incoming.popleft()

        men_prf.append(incoming)

    men_eng = [-1]*N
    women_eng = [-1]*N

    while (singleRemaining(men_eng)):
        for i in range(N):
            if men_eng[i]== -1:
                top = men_prf[i].popleft()

                if women_eng[top-1]==-1:
                    women_eng[top-1] =i+1
                    men_eng[i] = top
                else:
                    competition = women_eng[top-1]

                    if women_prf[top-1].index(i+1)<women_prf[top-1].index(competition):
                        women_eng[top-1]= i+1
                        men_eng[i] = top
                        men_eng[competition-1]=-1
    for i in range(N):
        print(i+1,men_eng[i])
    T -=1

# print(f"Finish time : {time.time() - start}")


# Definition for singly-linked list.
from typing import List

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

class Solution:
    """
    Input: l1 = [2,4,3], l2 = [5,6,4]
    Output: [7,0,8]
    Explanation: 342 + 465 = 807.
    """
    @staticmethod
    def sum_reverse_order_list_node(li: ListNode) -> int:

        nums_list: List[int] = []
        while li.next:
            nums_list.append(li.val)
            li = li.next
        nums_list.append(li.val)
        return sum([num * 10 ** i for i, num in enumerate(nums_list)])

    def add_two_numbers(self, l1: ListNode, l2: ListNode) -> ListNode:

        sum_l1_l2: int = self.sum_reverse_order_list_node(l1) + self.sum_reverse_order_list_node(l2)

        sum_l1_l2_nums_list: List[int] = []
        while sum_l1_l2 >= 10:
            sum_l1_l2_nums_list.append(sum_l1_l2 % 10)
            sum_l1_l2 //= 10
        sum_l1_l2_nums_list.append(sum_l1_l2)

        node: ListNode = None
        nodes: List[ListNode] = []
        for i, num in enumerate(sum_l1_l2_nums_list[::-1]):
            node = ListNode(num, None) if i == 0 else ListNode(num, nodes[i - 1])
            nodes.append(node)
        return node


from django.shortcuts import render, get_object_or_404
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
from .models import Listing
from listings.choices import bedroom_choices, state_choices, price_choices

# Create your views here.

# controllers for listings
def index(request):
    listings = Listing.objects.order_by('-list_date').filter(is_published=True)
    # pagination
    paginator = Paginator(listings, 6)
    page = request.GET.get('page')
    paged_listings = paginator.get_page(page)
    # pass in the context dictionary to the render
    # life can be so easy yet we complicate it.
    context = {
        'listings': paged_listings
    }
    return render(request, 'listings/listings.html', context)

def listing(request, listing_id):
    # get single listing from db get or 404

    listing = get_object_or_404(Listing, pk=listing_id)
    context = {
        'listing': listing
    }
    return render(request, 'listings/listing.html', context)

def search(request):
    # query_set list
    queryset_list = Listing.objects.order_by('-list_date')
    # keywords
    if 'keywords' in request.GET:
        keywords = request.GET.get('keywords')
        if keywords:
            # icontains checks if the selected property contains keyword
            queryset_list = queryset_list.filter(description__icontains=keywords)
    # city
    if 'city' in request.GET:
        city = request.GET.get('city')
        if city:
            #
            queryset_list = queryset_list.filter(city__iexact=city)
    # state

    if 'state' in request.GET:
        state = request.GET.get('state')
        if state:
            #
            queryset_list = queryset_list.filter(state__iexact=state)

    # bedroom
    if 'bedrooms' in request.GET:
        bedrooms = request.GET.get('bedrooms')
        if bedrooms:
            #
            queryset_list = queryset_list.filter(bedrooms__lte=bedrooms)
    # price
    if 'price' in request.GET:
        price = request.GET.get('price')
        price = float(price.replace(',', ''))
        if price:
            #
            queryset_list = queryset_list.filter(price__lte=price)

    context = {
        'state_choices': state_choices,
        'bedroom_choices': bedroom_choices,
        'price_choices': price_choices,
        'listings': queryset_list
    }
    return render(request, 'listings/search.html', context)


offset = int(open('input').readline()[:7])
inp = [int(c) for c in open('input').readline()] * 10000
inp = inp[offset:]

def compute(inp, total):
    new_total = 0
    result = []
    for i in inp:
        v = abs(total) % 10
        result.append(v)
        total -= i
        new_total += v
    return result, new_total

total = sum(inp)

for i in range(100):
    inp, total = compute(inp, total)

print(inp[:8])


from ..users.models import User
from src.users.models import User
from django.shortcuts import get_object_or_404
import datetime

# def compare_user_names(name):
#     exist = User.objects.filter(username = name).last()
#     if(exist):
#         print(exist.username)
#         return int(exist.username.split('.')[1])
#     else:
#         return 0

def add_user(image, username, uuid):

    # try:
    if User.objects.filter(username=username).exists():
        return {"status": True, "message": "Username Already Exists, please choose new username", "username": username}

    user = User.objects.create(profile_picture=image, username=username, id=uuid)
    print("User Created")
    print(user)

    status = {
        "status": True,
        "message": "Person Has Been Added",
        "data": {
            "username": username,
            "auth_token": str(user.auth_token)
        }
    }
    return status
    # except:
    #     status = {"status":False,"message":"Unable To Add Person"}
    #     return status

# def add_temp_user(request,name):
#     TempPerson.objects.create(name=name,image=request.FILES['image'])
#     status = {"status": True, "message":"Person Has Been Added To Temporary Storage For Batch Process"}
#     return status

# def get_auth_token(name):
#     try:
#         user = User.objects.get(username=name)
#         token = str(user.auth_token)
#     except:
#         token = "DONT_USE_THIS_USER"
#     return token


import torch

from .density import Density

class SplitDensity(Density):
    def __init__(self, density_1, density_2, dim, non_square=False):
        super().__init__()

        self.density_1 = density_1
        self.density_2 = density_2
        self.dim = dim
        self.non_square = non_square

    def _elbo(self, x):
        x1, x2 = torch.chunk(x, chunks=2, dim=self.dim)
        prior_dict_1 = self.density_1.elbo(x1)
        prior_dict_2 = self.density_2.elbo(x2)

        return {
            "elbo": prior_dict_1["elbo"] + prior_dict_2["elbo"],
            "prior-dict": prior_dict_1, # HACK: Assumes prior_dict_1 is more important
            "prior-dict-2": prior_dict_2
        }

    def _jvp(self, x, v):
        return {
            "x": self.pad_inputs(x)["x"],
            "jvp": self.pad_inputs(v)["x"]
        }

    def _fixed_sample(self, noise):
        x1 = self.density_1.fixed_sample(noise=noise)

        if self.non_square:
            return self.pad_inputs(x1)["x"]
        else:
            x2 = self.density_2.fixed_sample(noise=noise)
            return torch.cat((x1, x2), dim=self.dim)

    def _sample(self, num_samples):
        x1 = self.density_1.sample(num_samples)

        if self.non_square:
            return self.pad_inputs(x1)["x"]
        else:
            x2 = self.density_2.sample(num_samples)
            return torch.cat((x1, x2), dim=self.dim)

    def pad_inputs(self, x1):
        x2 = torch.zeros_like(x1)
        return {"x": torch.cat((x1, x2), dim=self.dim)}


#!/usr/bin/python3

"""
Gather data from an API
"""

import requests
from sys import argv

if __name__ == "__main__":
    user_id = argv[1]
    base_url = "https://jsonplaceholder.typicode.com/"
    employee = requests.get(base_url + "users/{}".format(user_id)).json()
    tasks = requests.get(base_url + "todos", params={"userId": user_id}).json()

    completed_tasks = []
    for task in tasks:
        if task.get("completed"):
            completed_tasks.append(task.get("title"))

    print("Employee {} is done with tasks({}/{}):".format(
        employee.get("name"), len(completed_tasks), len(tasks)))

    for task in completed_tasks:
        print("\t {}".format(task))


print('Bienvenido a "Hempire Calculator"')

categories = [
    {'id': 0, 'name': 'Indica'},
    {'id': 1, 'name': 'Hybrid'},
    {'id': 2, 'name': 'Sativa'}
]

strains = [
    {'id': 0, 'name': 'Afghani', 'category': 0},
    {'id': 1, 'name': 'Northern Lights', 'category': 0},
    {'id': 2, 'name': 'Hindu Kush', 'category': 0},
    {'id': 3, 'name': 'Stunk #1', 'category': 1},
    {'id': 4, 'name': 'Chemdawg', 'category': 1},
    {'id': 5, 'name': 'G13 Haze', 'category': 1},
    {'id': 6, 'name': 'Sour Diesel', 'category': 2},
    {'id': 7, 'name': 'Haze', 'category': 2},
    {'id': 8, 'name': 'Jack Herer', 'category': 1},
    {'id': 9, 'name': 'none', 'category': ''},
]

strainMaestries = [
    {'id': 0, 'level': 1, 'buds': 1},
    {'id': 1, 'level': 2, 'buds': 2},
    {'id': 2, 'level': 3, 'buds': 3},
    {'id': 3, 'level': 4, 'buds': 4},
    {'id': 4, 'level': 5, 'buds': 5},
    {'id': 5, 'level': 6, 'buds': 6},
    {'id': 6, 'level': 7, 'buds': 7}
]

pots = [
    {'id': 0, 'name': 'normal', 'timeAceleration': 0},
    {'id': 1, 'name': 'magic', 'timeAceleration': 0.5}
]

def recorreDictionary(dictionary=''):
    if dictionary == '' or type(dictionary) == 'str':
        print('Diccionario vacio')
        return False

    print('\nEJECUTADO DESDE UNA FUNCIÓN\n')
    for row in dictionary:
        print('Id: %s\tName: %s' % (row['id'], row['name']))
    return 'We did it'

# https://hempire.fandom.com/
print('Categorias')
for category in categories:
    print('\t %d->%s' % (category['id'], category['name']))
print()

print('Cepas')
for strain in strains:

    idStrain = strain['id']

    if idStrain in [5, 6, 7]:
        nameStrain = strain['name'].upper()
        print('\n/// %s' % format(nameStrain))

    if idStrain == 5:
        # Test dictionary whit for bucle to get key and value
        for key, value in strain.items():
            print('{0} : {1} '.format(
                key, value), end='\t')
        print('\n//////')
        continue

    if idStrain == 6:
        # Test dictionary whit for bucle to get key and value
        for value in strain:
            print('{0} : {1} '.format(
                value, strain[value]), end='\t')
        print('\n//////')
        continue

    if idStrain == 7:
        # Test dictionary whit for bucle to get values
        for value in strain.values():
            print(value, end='\t')
        print('\n//////')
        continue

    if idStrain == 8:
        # Test to modify key value
        strain['category'] = 2
        print('Elementos: ', len(strain))

    if idStrain == 9:
        # Eliminar atributo con pop
        strain.pop("id")
        print(strain)

        # Eliminar atributo con del
        del strain["name"]
        print(strain)

        # Eliminar atributo con clear
        strain.clear()
        print(strain)
        continue

    print('\tCepa: {0}\t\tCategoria:{1}'.format(
          strain['name'], categories[strain['category']]['name']))
print()

print('Niveles de maestria para cepas disponibles:')
for mastery in strainMaestries:
    print('\tNivel: {0}, Cogollos Adicionales: {1}'.format(
        mastery['level'], mastery['buds'], end='\t'))

print()
print('Tipos de macetas:')
for pot in pots:
    print('\tTipo: {0}\tReducion de tiempo: {1}%'.format(
        pot['name'], int(pot['timeAceleration']*100)))

strains_bk = strains.copy()
print('My Strains count: %s' % len(strains_bk))

myStrain = []

for item in strains_bk:
    if len(item) == 0:
        continue

    item.update({'count': 0})
    myStrain.append(item)

# Call function whit params
# recorreDictionary(myStrain)

# Call function whit params whitout params when call
# recorreDictionary()

# whit return
x = recorreDictionary(myStrain)
print('RESULT:\t', x.upper())
# Sin retorno
recorreDictionary(myStrain)


import json
import time

from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.conf import settings

from profiles.models import Profile
from products.models import Tour
from .models import Order, OrderItem

class StripeWH_Handler:
    """Handle Stripe webhooks"""

    def __init__(self, request):
        self.request = request

    def _send_confirmation_email(self, order):
        """
        Send the user a confirmation email
        """
        customer_email = order.email
        subject = render_to_string(
            'checkout/confirmation_emails/confirmation_email_subject.txt',
            {'order': order}
        )
        body = render_to_string(
            'checkout/confirmation_emails/confirmation_email_body.txt',
            {
                'order': order,
                'contact_email': settings.DEFAULT_FROM_EMAIL,
                'contact_number': settings.DEFAULT_CONTACT_NUMBER,
                }
        )
        send_mail(subject, body, settings.DEFAULT_FROM_EMAIL, [customer_email])

    def handle_event(self, event):
        """
        Handle a generic/unknown/unexpected webhook event
        """
        return HttpResponse(
            content=f'Unhandled webhook received: {event["type"]}',
            status=200)

    def handle_payment_intent_succeeded(self, event):
        """
        Handle the payment_intent.succeeded webhook from Stripe
        """
        intent = event.data.object
        pid = intent.id
        bag = intent.metadata.bag
        save_info = intent.metadata.save_info

        billing_details = intent.charges.data[0].billing_details
        grand_total = round(intent.charges.data[0].amount / 100, 2)

        # cleans data in billing details
        for field, value in billing_details.address.items():
            if value == "":
                billing_details.address[field] = None

        profile = None
        username = intent.metadata.username
        if username != 'AnonymousUser':
            profile = Profile.objects.get(
                user__username=username
                )
            if save_info == 'save':
                profile.default_phone_number = billing_details.phone
                profile.default_country = billing_details.address.country
                profile.default_town_or_city = billing_details.address.city
                profile.default_street_address1 = billing_details.address.line1
                profile.default_street_address2 = billing_details.address.line2
                profile.default_county = billing_details.address.state
                profile.save()

        order_exists = False
        attempt = 1
        while attempt <= 10:
            try:
                order = Order.objects.get(
                    name__iexact=billing_details.name,
                    email__iexact=billing_details.email,
                    phone_number__iexact=billing_details.phone,
                    country__iexact=billing_details.address.country,
                    town_or_city__iexact=billing_details.address.city,
                    street_address1__iexact=billing_details.address.line1,
                    street_address2__iexact=billing_details.address.line2,
                    county__iexact=billing_details.address.state,
                    grand_total=grand_total,
                    original_bag=bag,
                    stripe_pid=pid,
                )
                order_exists = True
                break
            except Order.DoesNotExist:
                attempt += 1
                time.sleep(1)
        if order_exists:
            self._send_confirmation_email(order)
            return HttpResponse(
                content=(
                    f'Webhook received: {event["type"]}'
                    f' | SUCCESS: Verified order already in database'),
                status=200
            )
        else:
            order = None
            try:
                order = Order.objects.create(
                    profile=profile,
                    name=billing_details.name,
                    email=billing_details.email,
                    phone_number=billing_details.phone,
                    country=billing_details.address.country,
                    postcode=billing_details.address.postal_code,
                    town_or_city=billing_details.address.city,
                    street_address1=billing_details.address.line1,
                    street_address2=billing_details.address.line2,
                    county=billing_details.address.state,
                    original_bag=bag,
                    stripe_pid=pid,
                )
                for tour_date_booked, quantity in json.loads(bag).items():
                    tour_id = tour_date_booked.split()[0]
                    tour = get_object_or_404(Tour, pk=tour_id)
                    date_booked = ' '.join(
                        tour_date_booked.split()[2].split('-')
                        )
                    order_item = OrderItem(
                        order=order,
                        tour=tour,
                        number_of_guests=quantity,
                        date_of_trip_or_event=date_booked,
                    )
                    order_item.save()
            except Exception as e:
                if order:
                    order.delete()
                return HttpResponse(
                    content=(
                        f'Webhook received: {event["type"]}'
                        f' | ERROR: {e}'),
                    status=500
                )
        self._send_confirmation_email(order)
        return HttpResponse(
            content=(
                f'Webhook received: {event["type"]}'
                f' | SUCCESS: Created order in webhook'),
            status=200)

    def handle_payment_intent_payment_failed(self, event):
        """
        Handle the payment_intent.payment_failed webhook from Stripe
        """
        return HttpResponse(
            content=f'Webhook received: {event["type"]}',
            status=200)


from flask import Flask, request, render_template
import sqlite3
import datetime
import logging

logging.basicConfig(filename="log.log", level=logging.INFO, filemode="w")
logger = logging.getLogger()

plain_v1_table = 'CREATE TABLE v1(organisation TEXT, application TEXT, current_version TEXT, last_version TEXT,' \
                 ' version_update_time TEXT, package_link TEXT, pin TEXT)'

def get_date_str():
    now = datetime.datetime.now()
    return now.strftime("%m/%d/%Y, %H:%M:%S")

def init_db():
    conn = sqlite3.connect('database.db')
    logger.info("connected to database successfully")
    # Check if table is complete
    try:
        conn.execute(plain_v1_table)
        logger.warning("database ' V1-Table ' created.")
        conn.close()

    except sqlite3.OperationalError:
        conn.close()
        logger.info("database check successfully")

# setup app
init_db()
app = Flask(__name__)

def api_query():
    con = sqlite3.connect("database.db")
    con.row_factory = sqlite3.Row
    cur = con.cursor()
    cur.execute("select * from v1")
    rows = cur.fetchall()
    return rows

def check_version(ext_ver, int_ver):
    if ext_ver == int_ver:
        result = ""

@app.route("/")
def index():
    logger.info(f"{request.access_route} -> Homepage")
    return render_template("home.html")

@app.route("/register")
def new_entry():
    logger.info(f"{request.access_route} -> Register")
    return render_template("register.html")

# api routes
@app.route("/api/v1/add_rec", methods=['POST'])
def addrec_v1():
    logger.warning(f"{request.access_route} -> Register Method")
    if request.method == 'POST':
        try:
            organisation = request.form['organisation']
            application = request.form['application']
            current_version = request.form['current_version']
            last_version = request.form['last_version']
            package_link = request.form['package_link']
            pin = request.form['pin']

            with sqlite3.connect("database.db") as con:
                cur = con.cursor()
                cur.execute("INSERT INTO v1 (organisation,"
                            "application,current_version,last_version,version_update_time,package_link, pin)"
                            "VALUES (?,?,?,?,?,?,?)", (organisation, application, current_version, last_version,
                                                       get_date_str(), package_link, pin))
            con.commit()
            msg = "Record successfully added"

        except:
            con.rollback()
            msg = "error in insert operation"

        finally:
            con.close()
            return render_template("result.html", msg=msg)

@app.route("/api/v1/<org>", methods=['GET'])
def api(org):
    logger.info(f"{request.access_route} -> {org}")
    con = sqlite3.connect("database.db")
    cursor = con.cursor()
    sql = f"SELECT * FROM v1 WHERE organisation ='{org}'"
    cursor.execute(sql)
    result = cursor.fetchall()

    if len(result) < 1:
        logger.warning("org not registerd")
        return render_template("result.html", msg=f"No entry for:'{org}'.")
    # at least 1 entry for org found
    else:
        application = request.args.get("app")
        user_version = request.args.get("version")

        # process data if arg provided
        if application is not None and user_version is not None:
            logger.warning(result)
            for x in result:
                if x[1] == application and x[2] == user_version:
                    return f"/{org}/{application}?match=true"

                if x[1] == application and x[3] == user_version:
                    return f"/{org}/{application}?match=behind&new={x[4]}&link={x[5]}"

                if x[1] == application and x[2] != user_version and x[3] != user_version:
                    return f"/{org}/{application}?match=far-behind&new={x[4]}&link={x[5]}"

                logger.warning(type(x))

        # do not handle request, args missing
        elif application is None or user_version is None:
            logger.error("api -> handle request -> args missing")
            return "denied"

        else:
            return "Something happened."

if __name__ == "__main__":
    app.run()