# -*- coding: utf-8 -*-
#
# Copyright (C) 2016, 2017, 2018, 2019 RACC
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the 1-N General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the 1-N General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

from __future__ import unicode_literals

import xbmc
import xbmcgui
import xbmcaddon
import xbmcplugin
from xbmcgui import ListItem
from routing import Plugin

import sys
import os
import traceback
import time

import requests
from datetime import timedelta
from requests_cache import CachedSession
from Cryptodome.Cipher import AES
from hashlib import md5
from binascii import b2a_hex

try:
    from http.cookiejar import LWPCookieJar
except ImportError:
    from cookielib import LWPCookieJar
try:
    from urllib.parse import quote_from_bytes as orig_quote
except ImportError:
    from urllib import quote as orig_quote
try:
    from urllib.parse import unquote_to_bytes as orig_unquote
except ImportError:
    from urllib import unquote as orig_unquote

addon = xbmcaddon.Addon()
plugin = Plugin()
plugin.name = addon.getAddonInfo("name")
player_user_agent = "Lavf/56.15.102"
user_agent = "okhttp/3.10.0"
USER_DATA_DIR = xbmc.translatePath(addon.getAddonInfo("profile")).decode("utf-8")  # !!
CACHE_TIME = int(addon.getSetting("cache_time"))
CACHE_FILE = os.path.join(USER_DATA_DIR, "cache")
COOKIE_FILE = os.path.join(USER_DATA_DIR, "lwp_cookies.dat")
expire_after = timedelta(hours=CACHE_TIME)

if not os.path.exists(USER_DATA_DIR):
    os.makedirs(USER_DATA_DIR)

s = CachedSession(
    CACHE_FILE,
    allowable_methods=("GET", "POST"),
    expire_after=expire_after,
    old_data_on_error=True,
    ignored_parameters=["data"],
)
s.hooks = {"response": lambda r, *args, **kwargs: r.raise_for_status()}
s.cookies = LWPCookieJar(filename=COOKIE_FILE)
if os.path.isfile(COOKIE_FILE):
    s.cookies.load(ignore_discard=True, ignore_expires=True)

data_url = "http://swiftstreamz.com/SwiftPanel/apiv1.php"
cat_url = "http://swiftstreamz.com/SwiftPanel/apiv1.php?get_category"
list_url = "http://swiftstreamz.com/SwiftPanel/apiv1.php?get_channels_by_cat_id={0}"

def quote(s, safe=""):
    return orig_quote(s.encode("utf-8"), safe.encode("utf-8"))

def unquote(s):
    return orig_unquote(s).decode("utf-8")

def get_post_data():
    _key = b"cLt3Gp39O3yvW7Gw"
    _iv = b"bRRhl2H2j7yXmuk4"
    cipher = AES.new(_key, AES.MODE_CBC, iv=_iv)
    _time = str(int(time.time()))
    _hash = md5(
        "{0}e31Vga4MXIYss1I0jhtdKlkxxwv5N0CYSnCpQcRijIdSJYg".format(_time).encode("utf-8")
    ).hexdigest()
    _plain = "{0}&{1}".format(_time, _hash).ljust(48).encode("utf-8")
    cry = cipher.encrypt(_plain)
    return b2a_hex(cry).decode("utf-8")

@plugin.route("/refresh")
def refresh():
    s.cache.clear()
    xbmc.executebuiltin("Container.Refresh")

@plugin.route("/")
def root():
    headers = {"Connection": "Keep-Alive", "Accept-Encoding": "gzip"}
    req = requests.Request("GET", cat_url, headers=headers)
    prepped = req.prepare()
    r = s.send(prepped, timeout=10)
    res = r.json(strict=False)

    list_items = []
    for cat in res["LIVETV"]:
        li = ListItem(cat["category_name"])
        li.setArt({"thumb": "{0}|User-Agent={1}".format(cat["category_image"], quote(user_agent))})
        url = plugin.url_for(list_channels, cat_id=cat["cid"])
        list_items.append((url, li, True))

    xbmcplugin.addDirectoryItems(plugin.handle, list_items)
    xbmcplugin.endOfDirectory(plugin.handle)

@plugin.route("/list_channels/<cat_id>")
def list_channels(cat_id=None):
    list_items = []
    headers = {"Connection": "Keep-Alive", "Accept-Encoding": "gzip"}
    req = requests.Request("GET", list_url.format(cat_id), headers=headers)
    prepped = req.prepare()
    r = s.send(prepped, timeout=10)
    res = r.json(strict=False)

    refresh_streams = "RunPlugin({0})".format(plugin.url_for(refresh))
    for ch in res["LIVETV"]:
        image = "{0}|User-Agent={1}".format(ch["channel_thumbnail"], quote(user_agent))
        li = ListItem(ch["channel_title"])
        li.setProperty("IsPlayable", "true")
        li.addContextMenuItems([("Refresh Streams", refresh_streams)])
        li.setArt({"thumb": image, "icon": image})
        li.setInfo(type="Video", infoLabels={"Title": ch["channel_title"], "mediatype": "video"})
        li.setContentLookup(False)
        url = plugin.url_for(play, cat_id=cat_id, channel_id=ch.get("id"))
        list_items.append((url, li, False))

    xbmcplugin.addDirectoryItems(plugin.handle, list_items)
    xbmcplugin.endOfDirectory(plugin.handle)

@plugin.route("/play/<cat_id>/<channel_id>/play.pvr")
def play(cat_id, channel_id):
    headers = {"Connection": "Keep-Alive", "Accept-Encoding": "gzip"}
    req = requests.Request("GET", list_url.format(cat_id), headers=headers)
    prepped = req.prepare()
    r = s.send(prepped, timeout=10)
    res = r.json(strict=False)

    for ch in res["LIVETV"]:
        if ch.get("id") == channel_id:
            title = ch.get("channel_title")
            image = "{0}|User-Agent={1}".format(ch["channel_thumbnail"], quote(user_agent))
            stream_list = ch.get("stream_list")

    post_data = {"data": get_post_data()}
    headers = {
        "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
        "Connection": "Keep-Alive",
        "Accept-Encoding": "gzip",
    }
    req = requests.Request("POST", data_url, data=post_data, headers=headers)
    prepped = req.prepare()
    r = s.send(prepped, timeout=10)
    data = r.json(strict=False)
    token_list = data["LIVETV"]["token_list"]

    for _stream in stream_list:
        stream_url = _stream.get("stream_url")
        stream_token = _stream.get("token")
        break

    for _token in token_list:
        if _token["t_id"] == stream_token:
            token_link = _token["token_link"]
            break

    with s.cache_disabled():
        post_data = {"data": get_post_data()}
        headers = {
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
            "Connection": "Keep-Alive",
            "Accept-Encoding": "gzip",
        }
        req = requests.Request("POST", token_link, data=post_data, headers=headers)
        prepped = req.prepare()
        r = s.send(prepped, timeout=10)
        auth_token = r.text.partition("=")[2]

    auth_token = "".join(
        [
            auth_token[:-59],
            auth_token[-58:-47],
            auth_token[-46:-35],
            auth_token[-34:-23],
            auth_token[-22:-11],
            auth_token[-10:],
        ]
    )
    media_url = "{0}?wmsAuthSign={1}|User-Agent={2}".format(
        stream_url, auth_token, quote(player_user_agent)
    )
    li = ListItem(title, path=media_url)

    if "playlist.m3u8" in media_url:
        if addon.getSetting("inputstream") == "true":
            li.setMimeType("application/vnd.apple.mpegurl")
            li.setProperty("inputstreamaddon", "inputstream.adaptive")
            li.setProperty("inputstream.adaptive.manifest_type", "hls")
            li.setProperty("inputstream.adaptive.stream_headers", media_url.split("|")[-1])
        else:
            li.setMimeType("application/vnd.apple.mpegurl")
    else:
        li.setMimeType("video/x-mpegts")

    li.setArt({"thumb": image, "icon": image})
    li.setContentLookup(False)
    xbmcplugin.setResolvedUrl(plugin.handle, True, li)

if __name__ == "__main__":
    try:
        plugin.run(sys.argv)
        s.cookies.save(ignore_discard=True, ignore_expires=True)
        s.close()
    except requests.exceptions.RequestException as e:
        dialog = xbmcgui.Dialog()
        dialog.notification(plugin.name, str(e), xbmcgui.NOTIFICATION_ERROR)
        traceback.print_exc()
        xbmcplugin.endOfDirectory(plugin.handle, False)
    except (ImportError, UnicodeDecodeError):
        """ Invalidate cache when requests version changes """
        s.cache.clear()


from flask import render_template
from sqlite3 import *
from db_config import *
from offre import offre
from article import Article, ArticlesListe
from smtplib import *

def index():
    return render_template('index.html')

def search(args=None):
    if args == None:
        return render_template('search.html')
    else:
        return render_template('search.html', args=args)

def process_search(args):

    search = list_offres()

    def process_arg_dom(nom, on):
        if on == 'on':
            search.add_domaine(nom)
            print(nom)
        else:
            search.remove_domaine(nom)

    def process_arg_level(nom, on):
        if on == 'on':
            search.add_level(nom)
        else:
            search.remove_level(nom)
    domaines = {'prog','reseau','web','ios', 'games', 'bdd'}
    for dom in domaines:
        if args.get('chk'+dom): process_arg_dom(dom, args.get('chk'+dom))

    if args.get('chk2'): process_arg_level('2', args.get('chk2'))
    if args.get('chk3'): process_arg_level('3', args.get('chk3'))
    if args.get('chk5'): process_arg_level('5', args.get('chk5'))
    if args.get('chk8'): process_arg_level('8', args.get('chk8'))

    if args.get('txt:salaire'):
        try:
            search.set_salaire(int(args.get('txt:salaire')))
        except:
            print('error')

    if args.get('txt:localisation'):
        search.set_localisation(args.get('txt:localisation'))

    if args.get('txt:txt'):
        search.set_txt(args.get('txt:txt'))

    # querry time !
    q = search.build().get()
    print(q)
    ans = []
    r = sqlite3.connect(db_name).execute(q)
    row = r.fetchone()
    while row:
        ans.append({table_list[i] : tuple(row)[i] for i in range(12)})
        ans[-1]['image'] = ans[-1]['image'].replace('//', '://')
        ans[-1]['lien'] = ans[-1]['lien'].replace('//', '://')
        ans[-1]['sources'] = ans[-1]['sources'].replace('//', '://')
        limit = 370
        while limit < len(ans[-1]['description']) and ans[-1]['description'][limit] != ' ':
            limit += 1
        ans[-1]['description'] = ans[-1]['description'][:limit]+' ...'
        row = r.fetchone()

    return render_template('results.html', results=ans)

def entreprise(entreprise_id):
    return render_template('entreprise.html', data=offre(entreprise_id))

def articles():
    return render_template('articlesList.html', data=ArticlesListe().get())

def article(id):
    return render_template('article.html', data=Article(id))

def contact():
    return render_template('contact.html')

def who():
    return render_template('who.html')

def send(args):
    db = sqlite3.connect(db_name)
    req = "INSERT INTO mail VALUES ('" + args.get('sender') + "' , '" + args.get('content') + "');"
    db.execute(req)
    db.commit()
    return render_template('sent.html')

def error(error_id):
    if error_id == 404:
        return render_template('404.html')
    else:
        return 'Error not Found'


import numpy as np
import healpy as hp
import os
import sys
from memory_profiler import profile

def get_dim(pol_type):
    """
    Calculates the dimension of a single pixel-pixel covariance matrix element
    and, the number of independent elements.
    """
    check_pol_type(pol_type)
    if pol_type == "IQU":
        dim = 3
    elif pol_type =="QU":
        dim = 2
    else:
        dim = 1

    ind_elements = int(dim*(dim+1)/2)

    return dim, ind_elements

def get_empty_matrices(nside, pol_type):
    npix = hp.nside2npix(nside)
    dim, ind_elements = get_dim(pol_type)
    inv_cov_matrix_local = np.zeros((npix, ind_elements), dtype=np.float)
    b_matrix_local = np.zeros((npix, dim), dtype=np.float)
    hitmap_local = np.zeros(npix, dtype=np.float)
    return inv_cov_matrix_local, b_matrix_local, hitmap_local

#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*

def flatten_block_matrix(block_matrix, pol_type):
    func_dict = {'IQU' : flatten_block_matrix_IQU, 'QU' : flatten_block_matrix_QU, 'I' : flatten_block_matrix_I}
    flat_matrix = func_dict[pol_type](block_matrix)
    return flat_matrix

def flatten_block_matrix_IQU(block_matrix):
    """
    In: 3x3 matrix.
    Out: 6 independent elements in a row.
    """
    num_elements = block_matrix.shape[0]
    flat_matrix = np.empty((num_elements, 6))

    flat_matrix[...,0] = block_matrix[..., 0, 0]
    flat_matrix[...,1] = block_matrix[..., 0, 0]
    flat_matrix[...,2] = block_matrix[..., 0, 2]
    flat_matrix[...,3] = block_matrix[..., 1, 1]
    flat_matrix[...,4] = block_matrix[..., 1, 2]
    flat_matrix[...,5] = block_matrix[..., 2, 2]

    return flat_matrix

def flatten_block_matrix_QU(block_matrix):
    """
    In: 2x2 matrix.
    Out: 3 independent elements in a row.
    """
    num_elements = block_matrix.shape[0]
    flat_matrix = np.empty((num_elements, 3))

    flat_matrix[..., 0] = block_matrix[..., 0, 0]
    flat_matrix[..., 1] = block_matrix[..., 0, 1]
    flat_matrix[..., 2] = block_matrix[..., 1, 1]

    return flat_matrix

def flatten_block_matrix_I(block_matrix):
    """
    In: 1 independent element for each pixel arranged in a 1-D array.
    Out: 1x1 matrix
    """
    num_elements = block_matrix.shape[0]
    flat_matrix = np.empty((num_elements, 1))

    flat_matrix[..., 0] = block_matrix[..., 0, 0]

    return flat_matrix

#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*

def make_block_matrix(flat_matrix, pol_type):
    """
    Transforms a row of the independent elements in the covariance matrix to a square matrix.
    Works for multiple pixel-pixel elements
    """
    func_dict = {'IQU' : make_block_matrix_IQU, 'QU' : make_block_matrix_QU, 'I' : make_block_matrix_I}
    block_matrix = func_dict[pol_type](flat_matrix)
    return block_matrix

def make_block_matrix_IQU(flat_matrix):
    """
    In: 6 independent elements in a row.
    Out: 3x3 matrix.
    """
    num_blocks = flat_matrix.shape[0]

    block_matrix = np.empty((num_blocks, 3, 3))

    block_matrix[..., 0, 0] = flat_matrix[..., 0]
    block_matrix[..., 0, 1] = flat_matrix[..., 1]
    block_matrix[..., 0, 2] = flat_matrix[..., 2]
    block_matrix[..., 1, 0] = block_matrix[..., 0, 1]
    block_matrix[..., 1, 1] = flat_matrix[..., 3]
    block_matrix[..., 1, 2] = flat_matrix[..., 4]
    block_matrix[..., 2, 0] = block_matrix[..., 0, 2]
    block_matrix[..., 2, 1] = block_matrix[..., 1, 2]
    block_matrix[..., 2, 2] = flat_matrix[..., 5]

    return block_matrix

def make_block_matrix_QU(flat_matrix):
    """
    In: 3 independent elements in a row.
    Out: 2x2 matrix.
    """
    num_blocks = flat_matrix.shape[0]

    block_matrix = np.empty((num_blocks, 2, 2))

    block_matrix[..., 0, 0] = flat_matrix[..., 0]
    block_matrix[..., 0, 1] = flat_matrix[..., 1]
    block_matrix[..., 1, 0] = block_matrix[..., 0, 1]
    block_matrix[..., 1, 1] = flat_matrix[..., 2]

    return block_matrix

def make_block_matrix_I(flat_matrix):
    """
    In: 1 independent element for each pixel arranged in a 1-D array.
    Out: 1x1 matrix
    """
    num_blocks = flat_matrix.shape[0]

    block_matrix = np.empty((num_blocks, 1, 1))

    block_matrix[..., 0, 0] = flat_matrix[..., 0]

    return block_matrix

#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*

def add_to_mm_matrices(hitpix, psi, psi_hwp, signal, inv_cov_matrix, b_matrix, hitmap, npix, pol_type):
    """
    Generates the pixel-pixel inverse covariance matrix.
    This convention does not have a 1/2 multiplied in the data model. That factor is accounted for in the calibration.
    The inv_cov_matrix and b_matrix are passed by reference and are updated by the routine.
    """
    check_pol_type(pol_type)
    func_dict = {'IQU' : add_to_mm_matrices_IQU, 'QU' : add_to_mm_matrices_QU, 'I' : add_to_mm_matrices_I}
    func_dict[pol_type](hitpix, psi, psi_hwp, signal, inv_cov_matrix, b_matrix, hitmap, npix)

def add_to_mm_matrices_IQU(hitpix, psi, psi_hwp, signal, inv_cov_matrix, b_matrix, hitmap, npix):
    n = np.bincount(hitpix, minlength=npix)
    pol_phase = psi + 2*psi_hwp
    cos_4 = np.bincount(hitpix, weights=np.cos(4*pol_phase), minlength=npix)

    hitmap += n

    inv_cov_matrix[..., 0] += n
    inv_cov_matrix[..., 1] += np.bincount(hitpix, weights=np.cos(2*pol_phase), minlength=npix)
    inv_cov_matrix[..., 2] += np.bincount(hitpix, weights=np.sin(2*pol_phase), minlength=npix)
    inv_cov_matrix[..., 3] += 0.5*(n + cos_4)
    inv_cov_matrix[..., 4] += 0.5*np.bincount(hitpix, weights=np.sin(4*pol_phase), minlength=npix)
    inv_cov_matrix[..., 5] += 0.5*(n - cos_4)

    b_matrix[..., 0] += np.bincount(hitpix, weights=signal, minlength=npix)
    b_matrix[..., 1] += np.bincount(hitpix, weights=signal*np.cos(2*pol_phase), minlength=npix)
    b_matrix[..., 2] += np.bincount(hitpix, weights=signal*np.sin(2*pol_phase), minlength=npix)

def add_to_mm_matrices_QU(hitpix, psi, psi_hwp, signal, inv_cov_matrix, b_matrix, hitmap, npix):
    n = np.bincount(hitpix, minlength=npix)
    pol_phase = psi + 2*psi_hwp
    cos_4 = np.bincount(hitpix, weights=np.cos(4*pol_phase), minlength=npix)

    hitmap += n

    inv_cov_matrix[..., 0] += 0.5*(n + cos_4)
    inv_cov_matrix[..., 1] += 0.5*np.bincount(hitpix, weights=np.sin(4*pol), minlength=npix)
    inv_cov_matrix[..., 2] += 0.5*(n - cos_4)

    b_matrix[..., 0] += np.bincount(hitpix, weights=signal*np.cos(2*pol), minlength=npix)
    b_matrix[..., 1] += np.bincount(hitpix, weights=signal*np.sin(2*pol), minlength=npix)

def add_to_mm_matrices_I(hitpix, psi, psi_hwp, signal, inv_cov_matrix, b_matrix, hitmap, npix):
    n = np.bincount(hitpix, minlength=npix)

    hitmap += n

    inv_cov_matrix[..., 0] += n

    b_matrix[..., 0] += np.bincount(hitpix, weights=signal, minlength=npix)

#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*

def get_covariance_matrix(inv_cov_matrix, hitmap, pol_type):
    dim, ind_elements = get_dim(pol_type)
    inv_cov_matrix_block = make_block_matrix(inv_cov_matrix, pol_type)
    mask_bad_pix(inv_cov_matrix_block, hitmap, pol_type)

    cov_matrix = np.linalg.inv(inv_cov_matrix_block)

    return cov_matrix

def get_sky_map(cov_matrix, b_matrix, hitmap, pol_type):
    sky_map = np.sum(cov_matrix*b_matrix[..., None], axis=1).T
    if pol_type == "IQU":
        sky_map[..., hitmap<3] = np.nan
    elif pol_type == "QU":
        sky_map[..., hitmap<2] = np.nan
    else:
        sky_map[..., hitmap<1] = np.nan
    return sky_map

#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*

def mask_bad_pix(matrix, hitmap, pol_type):
    if pol_type == "IQU":
        matrix[hitmap<3] = np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]])
    elif pol_type == "QU":
        matrix[hitmap<2] = np.array([[1.0, 0.0], [0.0, 1.0]])
    else:
        matrix[hitmap<1] = np.array([[1.0]])
    return matrix

def pointing_vec_to_hitpix(pointing_vec, nside):
    # Time-ordered array of pointing vectors to time-ordered array of hit pixels
    hitpix = hp.vec2pix(nside, pointing_vec[...,0], pointing_vec[...,1], pointing_vec[...,2])
    return hitpix

#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*
def check_pol_type(pol_type):
    assert pol_type in ['IQU', 'QU', 'I'], "pol_type has to be one of ['IQU','QU','I']. You have passes {}".format(pol_type)


# Train an agent from scratch with PPO2 and save package and learning graphs
# from OpenGL import GLU
import os
import glob
import time
import subprocess
import shutil
import gym
from gym_quad.envs import quad_env
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime
import imageio
from stable_baselines3.ppo import MlpPolicy
from stable_baselines3.common.vec_env import SubprocVecEnv, DummyVecEnv, VecNormalize
from stable_baselines3.common.vec_env import VecFrameStack
from stable_baselines3 import PPO
from stable_baselines3.common.monitor import Monitor
from stable_baselines3.common.results_plotter import load_results, ts2xy
from stable_baselines3.common.cmd_util import make_vec_env
from stable_baselines3.common.utils import get_device

class PPOtraining():
    def __init__(self, envParameters, initModelLoc=None) :
        self.step_stage = 0
        self.step_total = 800000

        self.env = None
        self.n_cpu = 8
        self.modelLoc = initModelLoc
        self.model = None
        self.stage = -1
        self.envParameters = envParameters
        self.createDirectories()

        #Attributes to store results across stages
        self.all_x = []
        self.all_y = []
        self.vert_x = []

        for i in self.envParameters[:,0]:
            self.changeStage()
            self.train()

    def createDirectories(self):
        self.models_dir = os.path.join(os.path.dirname(
        os.path.realpath(__file__)), "models/")

        self.models_tmp_dir = os.path.join(os.path.dirname(
        os.path.realpath(__file__)), "models_tmp/")
        self.log_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "tmp")
        self.gif_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "tmp_gif/")
        self.plt_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "plot")

        os.makedirs(self.log_dir, exist_ok=True)
        os.makedirs(self.gif_dir, exist_ok=True)
        os.makedirs(self.models_dir, exist_ok=True)
        os.makedirs(self.models_tmp_dir, exist_ok=True)
        os.makedirs(self.plt_dir, exist_ok=True)

    def updateEnv(self):
        if self.env != None :
            self.env.close()
        #env = quad_env.QuadEnv(legLengths=self.envParameters[self.stage,:4],legSigma=self.envParameters[self.stage,4],OUsigma=self.envParameters[self.stage,5],OUtau=self.envParameters[self.stage,6])

        #env.close() #just to update the parameters
        #self.env = [Monitor(env, self.log_dir+"/"+str(i), allow_early_resets=True) for i in range(self.n_cpu)]
        #env = gym.make("Quad-v0", legLengths=self.envParameters[self.stage,:4], legSigma=self.envParameters[self.stage,4], OUsigma=self.envParameters[self.stage,5], OUtau=self.envParameters[self.stage,6])
        #print(str(type(env)))
        env_kwargs = {'legLengths':self.envParameters[self.stage,:4],'legSigma':self.envParameters[self.stage,4],'OUsigma':self.envParameters[self.stage,5],'OUtau':self.envParameters[self.stage,6]}
        #print(env_kwargs)
        self.env=make_vec_env(quad_env.QuadEnv, n_envs=self.n_cpu, seed=None, start_index=0, monitor_dir=self.log_dir, wrapper_class=None, env_kwargs=env_kwargs, vec_env_cls=None, vec_env_kwargs=None)

        #self.env = gym.make("Quad-v0", legLengths = self.envParameters[self.stage,:4], legSigma = self.envParameters[self.stage,4], OUsigma = self.envParameters[self.stage,5], OUtau = self.envParameters[self.stage,6])
        #self.env = Monitor(self.env, self.log_dir, allow_early_resets=True)
        #self.env = DummyVecEnv( [lambda: self.env for i in range(self.n_cpu)] )
        #self.env = SubprocVecEnv([lambda: self.env for i in range(self.n_cpu)])
        #self.env = SubprocVecEnv(lambda : self.env)
        #env =self.custom_quad_env()
        #self.env = VecFrameStack(env, n_stack=self.n_cpu)

    def updateModel(self):
        if self.modelLoc==None:
            self.model = PPO(MlpPolicy, self.env, verbose=1)
            self.modelLoc = self.models_dir
        else :
            del self.model
            print(self.stage)
            self.model = PPO.load(self.modelLoc+"stage_"+str(self.stage-1)+"final.plk", env=self.env)
            print("loaded "+str((self.modelLoc+"stage_"+str(self.stage-1)+"final.plk")))

    def changeStage(self):
        self.stage = self.stage + 1
        self.updateEnv()

        self.updateModel()

    def train(self):
        start = time.time()
        self.model.learn(total_timesteps=self.step_total)

        self.model.save(self.modelLoc+"stage_"+str(self.stage)+"final.plk")
        print("saved "+str((self.modelLoc+"stage_"+str(self.stage)+"final.plk")))
        end = time.time()
        training_time = end - start
        print("Training of stage "+ str(self.stage) +" completed in "+ str(training_time) +" s !")
        self.step_stage = self.step_stage + self.step_total
        self.performance()
        self.createGif()

    def performance(self):

        #log_files = glob.glob(self.log_dir+"/*.csv")
        #df = pd.concat((pd.read_csv(f, header = 0) for f in log_files))
        #df.to_csv(self.log_dir+"/monitor.csv")
        x, y = ts2xy(load_results(self.log_dir), 'timesteps')
        #print(x)
        #print(y)
        y = self.moving_average(y, window=50)
        x = x[len(x) - len(y):]
        x = x + self.step_stage*np.ones(np.size(x))
        for i in x:
            try :
                self.all_x.append(i + vert_x[-1])
                appended_val = x[-1] + vert_x[-1]
            except :
                self.all_x.append(i)
                appended_val = x[-1]

        self.vert_x.append(appended_val)
        for i in y:
            self.all_y.append(i)
        #os.remove(os.path.join(self.log_dir, "/monitor.csv"))

        save_name = os.path.join(self.plt_dir, 'Curriculum_stage'+str(self.stage))
        #print(self.all_x)
        #print(self.all_y)
        fig = plt.figure('Curriculum' + str(self.step_stage)+"_stage"+str(self.stage))
        plt.plot(self.all_x, self.all_y)
        for i in self.vert_x:
            plt.axvline(x=i, linestyle='--', color='#ccc5c6', label='leg increment')
        plt.xlabel('Number of Timesteps')
        plt.ylabel('Rewards')
        plt.title('Curriculum learning' + " Smoothed")
        plt.savefig(save_name + ".png")
        plt.savefig(save_name + ".eps")
        print("plots saved...")
        #if self.stage==3:
        #    plt.show()

    def moving_average(self,values, window):
        weights = np.repeat(1.0, window) / window
        return np.convolve(values, weights, 'valid')

    def createGif(self):
        gif_name = "PPO_" + "stage_"+ str(self.stage)
        save_str = self.gif_dir + gif_name + '.gif'
        self.env.close()
        #env_gif = quad_env.QuadEnv(self.envParameters[self.stage,:4],self.envParameters[self.stage,4],self.envParameters[self.stage,5],self.envParameters[self.stage,6])
        env_gif = quad_env.QuadEnv(legLengths=self.envParameters[self.stage,:4],legSigma=self.envParameters[self.stage,4],OUsigma=self.envParameters[self.stage,5],OUtau=self.envParameters[self.stage,6])
        #env_gif = gym.make("Quad-v0", legLengths=self.envParameters[self.stage,:4], legSigma=self.envParameters[self.stage,4], OUsigma=self.envParameters[self.stage,5], OUtau=self.envParameters[self.stage,6])
        #del self.model

        #self.model = PPO2.load(self.modelLoc+"stage_"+str(self.stage)+"final.plk", env=self.env)
        images = []
        obs = env_gif.reset()
        img = env_gif.sim.render(
            width=400, height=400, camera_name="isometric_view")
        for _ in range(1000):
            action, _ = self.model.predict(obs)
            obs, _, _, _ = env_gif.step(action)
            img = env_gif.sim.render(
                width=400, height=400, camera_name="isometric_view")
            images.append(np.flipud(img))

        print("creating gif...")
        imageio.mimsave(save_str, [np.array(img)
                                   for i, img in enumerate(images) if i % 2 == 0], fps=29)
        print("gif created...")
        env_gif.close()

if __name__ == '__main__':
    print(get_device())
    Curriculum = np.array([[0.1,0.1,0.1,0.1,0.02,0.03,0.1],[0.35,0.35,0.35,0.35,0.04,0.06,0.2],[0.75,0.75,0.75,0.75,0.08,0.12,0.2],[1.0,1.0,1.0,1.0,0.16,0.24,0.2]])
    agent = PPOtraining(Curriculum)


import skimage
import sklearn
import sklearn_extra
from skimage import io
import sklearn.cluster
import sklearn_extra.cluster
import numpy as np

def initialize_K_centroids(image_arr, K):
    """ Choose K points from image_arr at random """
    random_selection = np.random.choice(len(image_arr), K, replace=False)
    return image_arr[random_selection, :]

def min_distances_array(image_arr, centroids):           #this returns distances from all points to their respective centroids
    len_image_arr = len(image_arr)
    len_centroids = len(centroids)
    min_distances_arr = np.zeros((len_image_arr))
    #print("distances_arr.shape :", distances_arr.shape)
    for index in range(len_image_arr):
        # Find distances to all of the K centroids; distances_arr is len_image_arr x len_centroids
        distances = np.linalg.norm(image_arr[index] - centroids, axis=1)    #axis=1 => computation is across columns
        #'distances' represents distance of image_arr[index] point to all the centroids => it is an 1-d array of len_centroids
        #broadcasting property of numpy is being used here https://numpy.org/doc/stable/user/basics.broadcasting.html
        #print("distance:", distance)
        min_distances_arr[index] = np.min(distances)
    return min_distances_arr

def find_closest_centroids(image_arr, centroids):
    len_image_arr = len(image_arr)
    closest_centroids_index_arr = np.zeros(len_image_arr) #closest_centroids_index_arr is an 1-d array
    for index in range(len_image_arr):
        # Find distances to all of the K centroids; len(distances) = K
        distances = np.linalg.norm(image_arr[index, :] - centroids[:,:], axis=1)    #axis=1 => computation is across columns
        #'distance' represents distance of image_arr[index] to all the centroids => it is an 1-d array of len_centroids
        #broadcasting property of numpy is being used here https://numpy.org/doc/stable/user/basics.broadcasting.html
        # Assign closest cluster to closest_centroids_index_arr[index]
        closest_centroids_index_arr[index] = np.argmin(distances)   #https://numpy.org/doc/stable/reference/generated/numpy.argmin.html

    return closest_centroids_index_arr       #each element in 'closest_centroids_index_arr' will have a value between 0 and K-1
                                             #len(closest_centroids_index_arr) = len_image_arr

def compute_new_centroids(image_arr, closest_centroids_index_arr, centroids_orig):
    n = image_arr.shape[1]   # n will be 3 for R,G,B
    K = len(centroids_orig)
    print("Entered compute_new_centroids")
    sum_min_distances = np.sum(min_distances_array(image_arr, centroids_orig))
    centroids = np.copy(centroids_orig)
    print("In compute_new_centroids function: Now will go through k in range(K)")
    for k in range(K):
        print("centroid k=", k)
        centroids_temp = np.copy(centroids)
        subset_image_arr = image_arr[np.where(closest_centroids_index_arr == k)]
        print("initial centroids for k = ", k, centroids)

        for i in range(len(subset_image_arr)):
            print("centroid k, point i in that cluster, len(subset_image_arr:", k,i, len(subset_image_arr))
            centroids_temp[k] = np.copy(subset_image_arr[i])
            sum_min_distances_temp = np.sum(min_distances_array(image_arr, centroids_temp))
            print("k, i, sum_min_distances, sum_min_distances_temp", k,i, sum_min_distances, sum_min_distances_temp)
            if sum_min_distances_temp < sum_min_distances:
                print("k, i centroids[k] getting ipdated")
                centroids[k] = np.copy(centroids_temp[k])  #https://docs.scipy.org/doc/numpy-1.9.2/reference/generated/numpy.copy.html
                sum_min_distances = sum_min_distances_temp
                print("updated centroids for k, i = ", k, i, centroids)
            if (i == (len(subset_image_arr) - 1)):
                print("centroids for k, i = ", k, i, centroids)

        print("final updated centroids for k = ", k, centroids)

    print("updated centroids being returned from compute_new_centroids function ", centroids)
    return centroids

def find_k_centroids(image_arr, K, max_iters=10):
    centroids = initialize_K_centroids(image_arr, K)
    print("initial centroids :", centroids)
    previous_centroids = np.copy(centroids)   # https://docs.scipy.org/doc/numpy-1.9.2/reference/generated/numpy.copy.html
    for count in range(max_iters):
        print("Entering iteration : ", count)
        closest_centroids_index_arr = find_closest_centroids(image_arr, centroids)
        print("Now calling compute_new_centroids" )
        centroids = compute_new_centroids(image_arr, closest_centroids_index_arr, centroids)
        print("centroids.shape, closest_centroids_index_arr.shape :", centroids.shape, closest_centroids_index_arr.shape)
        print("closest_centroids_index_arr :", closest_centroids_index_arr)
        print("previous_centroids :", previous_centroids)
        print("centroids :", centroids)
        if (centroids == previous_centroids).all():
            print("The centroids aren't moving anymore ")
            return centroids, closest_centroids_index_arr
        else:
            previous_centroids = np.copy(centroids)  # https://docs.scipy.org/doc/numpy-1.9.2/reference/generated/numpy.copy.html

    print("reached limit of max number of iterations :", count)
    print("Final centroids :", centroids)
    print("Final closest_centroids_index_arrcentroids :", closest_centroids_index_arr)
    return centroids, closest_centroids_index_arr

#Read the image into an np array (3D by default)
image_orig = skimage.io.imread('beach.bmp')
io.imshow(image_orig)
io.show()

#Dimension of the original image / np array
print("type(image_orig)", type(image_orig))
print("image_orig.shape", image_orig.shape)
print("image_orig: Number of dimensions, rows,cols, deep, total-size, length-of-1st-dim ", \
    image_orig.ndim, image_orig.shape[0], image_orig.shape[1], image_orig.shape[2], image_orig.size, len(image_orig))
print("Top left image_orig[0][0]", image_orig[0][0])
print("Top left image_orig[0, 0]", image_orig[0, 0])
print("Bottom right image_orig[213][319]", image_orig[213][319])
print("Bottom right image_orig[213, 319]", image_orig[213, 319])

#Flatten the original image; dimension of the flattened image / np array
rows = image_orig.shape[0]
cols = image_orig.shape[1]
image_f = image_orig.reshape(rows*cols, 3)
print("image_f.shape", image_f.shape)
print("image_f : Number of dimensions, rows, deep, total-size, length-of-1st-dim ", \
    image_f.ndim, image_f.shape[0], image_f.shape[1], image_f.size, len(image_f))
print("image_f[0]", image_f[0])
print("image_f[68479]", image_f[68479])  #214*320-1

#create a sample np array that samples every 5th pixel
image_f_s = np.empty([30375, 3])   #68480/2 ~ 30375
#print("Empty image_f_s: ", image_f_s)
for i in range(30375):
    image_f_s[i] = image_f[i*2]
print("Sampled image_f_s: ", image_f_s)
print("image_f_s: Number of dimensions, rows, deep, total-size, length-of-1st-dim ", image_f_s.ndim, image_f_s.shape[0], image_f_s.shape[1], \
    image_f_s.size, len(image_f_s))

centroid_colors, closest_centroid_colors_index_arr = find_k_centroids(image_f_s, 16, max_iters=1)
closest_centroid_colors_index_arr = find_closest_centroids(image_f_s, centroid_colors)

closest_centroid_colors_index_arr_int = closest_centroid_colors_index_arr.astype(int)

print("centroid_colors.dtype :", centroid_colors.dtype)
print("closest_centroid_colors_index_arr.dtype :", closest_centroid_colors_index_arr.dtype)
print("closest_centroid_colors_index_arr_int.dtype :", closest_centroid_colors_index_arr_int.dtype)
print("centroid_colors :", centroid_colors)
print("closest_centroid_colors_index_arr :", closest_centroid_colors_index_arr)
print("closest_centroid_colors_index_arr_int :", closest_centroid_colors_index_arr_int)

#Replace each pixel value with its nearby centroid and creating image_f_c_with_kmeans / 2D np array
image_f_s_c_with_kmedoids = centroid_colors[closest_centroid_colors_index_arr_int]

print("image_f_s_c_with_kmedoids shape: ", image_f_s_c_with_kmedoids.shape)
rows_c1 = image_f_s_c_with_kmedoids.shape[0]
cols_c1 = image_f_s_c_with_kmedoids.shape[1]
print("image_f_s_c_with_kmedoids rows, cols: ", rows_c1,cols_c1)
print("image_f_s_c_with_kmedoids[0]", image_f_s_c_with_kmedoids[0])

image_f_s_c_with_kmedoids_clip = np.clip(image_f_s_c_with_kmedoids.astype('uint8'), 0, 255)
print("image_f_s_c_with_kmedoids_clip[0]", image_f_s_c_with_kmedoids_clip[0])

#Reshape image to original dimension 135 x 225 = 30375
rows_c2_back_to_orig = 135
cols_c2_back_to_orig = 225
image_f_s_c_with_kmedoids_clip_final = image_f_s_c_with_kmedoids_clip.reshape(rows_c2_back_to_orig, cols_c2_back_to_orig, 3)
print("image_f_s_c_with_kmedoids_clip_final.shape", image_f_s_c_with_kmedoids_clip_final.shape)
print("image_f_s_c_with_kmedoids_clip_final.shape [0][1][2]", \
    image_f_s_c_with_kmedoids_clip_final.shape[0], image_f_s_c_with_kmedoids_clip_final.shape[1], image_f_s_c_with_kmedoids_clip_final.shape[2])
print(image_f_s_c_with_kmedoids_clip_final)

#Save and display output image
skimage.io.imsave('beach_c_without_kmedoids_lib-1.png', image_f_s_c_with_kmedoids_clip_final)
io.imshow(image_f_s_c_with_kmedoids_clip_final)
io.show()


import serial
import logging
import threading
import concurrent.futures

# if received execution done signal 'E', write messageline is_done True
# if new command string put to messageline, write messageline is_ready True
# if command line is sent, make is_done and is_ready False

class messageLine():
    def __init__(self):
        self.message = ""
        self.is_done = False
        self.is_ready = False
        self.event = threading.Event()
        self._lock = threading.Lock()

def sendMessage(msgLine, ser):
    while True:
        if msgLine.is_done and msgLine.is_ready:
            with msgLine._lock:
                ser.write(msgLine.message.encode())
                logging.info("Message sent: %s", msgLine.message[0:-1])

                msgLine.is_done = False
                msgLine.is_ready = False

        if msgLine.event.is_set():
            break

def receiveMessage(msgLine, ser):
    while True:
        if ser.in_waiting:
            with msgLine._lock:
                message = ser.readline().decode()[0:-2]
                logging.info("Message received: %s", message)

                if message == "Initialized" or len(message) == 1 and message[0] == 'E':
                    msgLine.is_done = True
                elif len(message) == 1 and message[0] == 'T':
                    break

    logging.info("Terminating serial communication")
    msgLine.event.set()

def putMessage(msgLine, string):
    msgLine.message = string + '\n'
    msgLine.is_ready = True

if __name__ == "__main__":
    format = "%(asctime)s: %(message)s"
    logging.basicConfig(format = format, level = logging.INFO, datefmt="%H:%M:%S")

    arduino = serial.Serial('COM7', 9600)
    logging.info("Initializing arduino")

    msg_line = messageLine()

    with concurrent.futures.ThreadPoolExecutor(max_workers = 2) as executor:
        executor.submit(receiveMessage, msg_line, arduino)
        executor.submit(sendMessage, msg_line, arduino)

        while True:
            string = input()
            putMessage(msg_line, string)


#!/usr/bin/env python

__author__ = "frankojis"

from flask import render_template, Blueprint, request, jsonify
import time
import threading
from datetime import datetime, timedelta

from core import utils
from core.fuel.facebook import CREDENTIALS_FILE, APP, validator, scraper, posts as FBPosts
from config import LISTENER_INI
from core.exhaust import posts, mongo

listener = Blueprint('listener', __name__, url_prefix='/listener', static_folder='static', template_folder='templates')

@listener.route("/")
def do_checks():
    status = utils.check_config(CREDENTIALS_FILE, APP)
    return render_template("precheck.html", modal=not status)

@listener.route("/update_credentials", methods=['POST'])
def update_credentials():
    access_token = request.form['token']
    page_id = request.form['id']
    validity = validator.validate_token(access_token, page_id)
    return validity

@listener.route("/db_connection/<action>", methods=['POST'])
def db_connection(action):
    from core.exhaust import mongo

    Mongo = mongo.Mongo()
    action_status = 'Error'
    if action == "clear":
        action_status = Mongo.delete_collections()
    elif action == "retrieve":
        action_status = Mongo.get_lastScrapeTime(APP)
        if action_status is None:
            action_status = Mongo.delete_collections()
    time.sleep(1)
    return action_status

@listener.route("/kickstart", methods=['POST'])
def environment_kicker():
    from core.engine import kicker

    kicker.submit_spark()
    time.sleep(10)
    kicker.flume_invoker()
    return "started"

@listener.route("/start_scrape/<timestamp>", methods=['POST'])
def start_scraper(timestamp):
    fb_creds = utils.get_params(CREDENTIALS_FILE, APP)
    days_back = utils.get_params(LISTENER_INI, 'GraphAPI')['days_ago']
    if timestamp != '0':
        start_time = timestamp
    else:
        start_time = (datetime.now() - timedelta(int(days_back))).strftime('%s')
    try:
        fb_posts = scraper.Scraper(fb_creds['page_id'], start_time)
        scraper_thread = threading.Thread(target=fb_posts.scrape_data, name="listener", args=("posts", ))
        scraper_thread.setDaemon("True")
        scraper_thread.start()
        time.sleep(1)
        return "initiated"
    except Exception:
        return "failure"

@listener.route("/graphs")
def display_graphs():
    page_info = utils.get_params(CREDENTIALS_FILE, APP)
    return render_template("graphs.html", page=page_info)

@listener.route("/trendplot")
def generate_trends():
    trends_list = posts.get_postTrends()
    if trends_list is not None:
        return jsonify(trends=trends_list)
    else:
        return "Error"

@listener.route("/polarityplot")
def generate_polarities():
    polarities, polarities_count = posts.get_postPolarities()
    if polarities is not None:
        return jsonify(polarities=polarities, count=polarities_count)
    else:
        return "Error"

@listener.route("/varietyplot")
def generate_varieties():
    varieties_list = posts.get_postVarietiesPercent()
    if varieties_list is not None:
        return jsonify(varieties=varieties_list)
    else:
        return "Error"

@listener.route("/graphs/<int:postts>")
def display_intoposts(postts):
    datestring = utils.get_datestring(postts)
    postdata = posts.get_postdata(datestring)
    page_info = utils.get_params(CREDENTIALS_FILE, APP)
    return render_template("posts.html", page=page_info, post=postdata)

@listener.route("/graphs/<postid>")
def get_comments(postid):
    comments_data = posts.get_postComments(postid)
    if comments_data['comments_count'] != 0:
        if comments_data['sentiment_analysed'] == 0:
            mongo.Mongo().update_document("COMMENT_SENTIMENT_FLAG", key='post_id', value=postid, document={'flag': 0})
            push_status = FBPosts.Posts(None, None, 'posts').push_lazycomments(comments_data)
            if push_status == "success":
                c_flag = 0
                while c_flag != 1:
                    time.sleep(1)
                    c_flag = mongo.Mongo().get_flagStatus(postid)
                    if c_flag == 'Error':
                        return 'Error'
                comments_data = posts.get_postComments(postid)
            else:
                return "Error"
        if comments_data is not None:
            if comments_data['comments_count'] != '0':
                refined_comments_data = dict()
                refined_comments_data['count'] = comments_data['comments_count']
                comments = list()
                for comment in comments_data['comments_data']:
                    comment_data = dict()
                    comment_data['message'] = comment['message']
                    comment_data['likes'] = comment['like_count']
                    comment_data['sentiment'] = comment['sentiment']
                    comment_data['comment_ts'] = utils.get_jsunixtimestamp(comment['created_time'])
                    comments.append(comment_data)
                refined_comments_data['data'] = comments
                return jsonify(comments=refined_comments_data)
            else:
                return "zero"
        else:
            return "Error"
    else:
        return "zero"

@listener.route("/postreach/<postid>")
def get_uniquereach(postid):
    attr_dicttuple = posts.get_attrdata(postid)
    counters = dict()
    unique_likes, unique_comments = set(), set()
    for key, vtuple in attr_dicttuple.iteritems():
        counters[key] = vtuple[1]
        if key == 'likes' and vtuple[0] is not None:
            for data in vtuple[0]:
                unique_likes.add(data['id'])
        elif key == 'comments' and vtuple[0] is not None:
            for data in vtuple[0]:
                unique_comments.add(data['from']['id'])
    unique_reach = unique_likes.union(unique_comments)
    did_both = len(unique_likes.intersection(unique_comments))
    json_set = utils.jsonifier(unique_reach, 'store')
    mongo.Mongo().update_document("UNIQUE_REACH", key='post_id', value=postid, document={'user_ids': json_set})
    return jsonify(reach=(len(unique_reach), did_both, counters))


from typing import AsyncGenerator, List
import sweeppy

from model import SweepSample

sweep_motor_speed = 2
sweep_sample_rate = 750

async def sweep_scan_generator(usb_port: str) -> AsyncGenerator[List[SweepSample], None]:
    with sweeppy.Sweep(usb_port) as sweep:
        sweep.set_motor_speed(sweep_motor_speed)
        sweep.set_sample_rate(sweep_sample_rate)
        sweep.start_scanning()

        for item in sweep.get_scans():
            yield list(map(lambda scan: SweepSample(scan.angle, scan.distance, scan.signal_strength), item.samples))


import json

import djstripe
import stripe
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.core.mail import mail_admins
from django.db import transaction
from django.http import JsonResponse, HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse
from django.utils.translation import ugettext_lazy as _
from django.views.decorators.http import require_POST
from djstripe.enums import PlanInterval
from djstripe.models import Product, Subscription
from djstripe import settings as djstripe_settings
from rest_framework import permissions
from rest_framework.decorators import api_view, permission_classes
from rest_framework.response import Response
from rest_framework.views import APIView

from apps.utils.decorators import catch_stripe_errors
from apps.web.meta import absolute_url
from .decorators import redirect_subscription_errors
from .helpers import get_friendly_currency_amount
from .metadata import get_active_products_with_metadata, \
    get_product_and_metadata_for_subscription, ACTIVE_PLAN_INTERVALS, get_active_plan_interval_metadata, \
    get_product_with_metadata, TEAMMATE_PRODUCT, EMAIL_PRODUCT

from apps.teams.decorators import team_admin_required, login_and_team_required
from apps.teams.models import Team
from ..users.models import CustomUser

class ProductWithMetadataAPI(APIView):

    def get(self, request, *args, **kw):
        products_with_metadata = get_active_products_with_metadata()
        return Response(
            data=[p.to_dict() for p in products_with_metadata]
        )

@redirect_subscription_errors
@login_required
def subscription(request, subscription_holder=None):
    subscription_holder = subscription_holder if subscription_holder else request.user
    if subscription_holder.has_active_subscription():
        return _view_subscription(request, subscription_holder)
    else:
        return _upgrade_subscription(request, subscription_holder)

def _get_payment_metadata_from_request(request):
    return {
        'user_id': request.user.id,
        'user_email': request.user.email,
    }

@login_required
def subscription_success(request):
    return _subscription_success(request, request.user)

def _subscription_success(request, subscription_holder):
    stripe.api_key = djstripe_settings.STRIPE_SECRET_KEY
    if not subscription_holder.has_active_subscription():
        subscription = subscription_holder.subscription
        if not subscription:
            messages.error(
                request,
                "Oops, it looks like there was a problem processing your payment. "
                "Please try again, or get in touch if you think this is a mistake."
            )
        else:
            # 3D-Secure workflow hopefully completed successfully,
            # re-sync the subscription and hopefully it will be active
            subscription.sync_from_stripe_data(subscription.api_retrieve())

    if subscription_holder.has_active_subscription():
        subscription_name = get_product_and_metadata_for_subscription(
            subscription_holder.active_stripe_subscription
        ).metadata.name
        messages.success(request, f"You've successfully signed up for {subscription_name}. "
                                  "Thanks so much for the support!")
        # notify admins when someone signs up
        mail_admins(
            subject=f"Hooray! Someone just signed up for a {subscription_name} subscription!",
            message="Email: {}".format(request.user.email),
            fail_silently=True,
        )

    assert isinstance(subscription_holder, Team)
    redirect = reverse('subscriptions:team_subscription_details', args=[subscription_holder.slug])

    return HttpResponseRedirect(redirect)

@api_view(['POST'])
@permission_classes([permissions.IsAuthenticated])
# @catch_stripe_errors
# @transaction.atomic
def create_customer(request, subscription_holder=None):
    """
    Create a Stripe Customer and Subscription object and map them onto the subscription_holder

    Expects the inbound POST data to look something like this:
    {
        'email': 'cory@example.com',
        'userId': '23',
        'payment_method': 'pm_1GGgZaIYTEadrA0y0tthZ5UH'
    }
    """
    subscription_holder = subscription_holder if subscription_holder else request.user
    request_body = json.loads(request.body.decode('utf-8'))
    user_id = int(request_body['user_id'])
    email = request_body['user_email']
    assert request.user.id == user_id
    assert request.user.email == email

    payment_method = request_body['payment_method']
    plan_id = request_body['plan_id']
    stripe.api_key = djstripe_settings.STRIPE_SECRET_KEY

    # first sync payment method to local DB to workaround https://github.com/dj-stripe/dj-stripe/issues/1125
    payment_method_obj = stripe.PaymentMethod.retrieve(payment_method)
    djstripe.models.PaymentMethod.sync_from_stripe_data(payment_method_obj)

    # create customer objects
    # This creates a new Customer in stripe and attaches the default PaymentMethod in one API call.
    customer = stripe.Customer.create(
      payment_method=payment_method,
      email=email,
      invoice_settings={
        'default_payment_method': payment_method,
      },
    )

    # create the local customer object in the DB so the subscription can use it
    djstripe.models.Customer.sync_from_stripe_data(customer)

    # create subscription
    subscription = stripe.Subscription.create(
      customer=customer.id,
      items=[
        {
          'plan': plan_id,
        },
      ],
      expand=['latest_invoice.payment_intent', 'pending_setup_intent'],
    )
    djstripe_subscription = djstripe.models.Subscription.sync_from_stripe_data(subscription)

    # set subscription object on the subscription holder
    subscription_holder.subscription = djstripe_subscription
    subscription_holder.save()

    data = {
        'customer': customer,
        'subscription': subscription
    }
    return JsonResponse(
        data=data,
    )

def _get_subscription_urls(subscription_holder):
    # get URLs for subscription helpers
    url_bases = [
        'create_customer',
        'create_stripe_portal_session',
    ]

    def _construct_url(base):
        return reverse(f'subscriptions:{base}')

    return {
        url_base: _construct_url(url_base) for url_base in url_bases
    }

@login_required
def subscription_demo(request, subscription_holder=None):
    subscription_holder = subscription_holder if subscription_holder else request.user
    return render(request, 'subscriptions/demo.html', {
        'active_tab': 'subscription_demo',
        'subscription': subscription_holder.active_stripe_subscription,
        'product': get_product_and_metadata_for_subscription(
            subscription_holder.active_stripe_subscription
        ),
        'subscription_urls': _get_subscription_urls(subscription_holder)
    })

@login_required
def subscription_gated_page(request, subscription_holder=None):
    subscription_holder = subscription_holder if subscription_holder else request.user
    if not subscription_holder.has_active_subscription():
        return render(request, 'subscriptions/subscription_required.html')
    else:
        return render(request, 'subscriptions/subscription_gated_page.html')

@team_admin_required
def team_subscription(request, team_slug):
    return subscription(request, subscription_holder=request.team)

@team_admin_required
def team_subscription_success(request, team_slug):
    return _subscription_success(request, subscription_holder=request.team)

@team_admin_required
@require_POST
def team_create_stripe_portal_session(request, team_slug):
    return create_stripe_portal_session(request, request.team)

@team_admin_required
@require_POST
@catch_stripe_errors
@transaction.atomic
def team_create_customer(request, team_slug):
    return create_customer(request, request.team)

@login_and_team_required
def team_subscription_demo(request, team_slug):
    return subscription_demo(request, request.team)

@login_and_team_required
def team_subscription_gated_page(request, team_slug):
    return subscription_gated_page(request, subscription_holder=request.team)

@api_view(['GET'])
@permission_classes([permissions.IsAuthenticated])
def stripe_info(request):
    subscription_holder: CustomUser = request.user

    has_active_subscription = subscription_holder.has_active_subscription()

    data = {
        'stripe_api_key': djstripe_settings.STRIPE_PUBLIC_KEY,
        'has_active_subscription': has_active_subscription,
    }
    return JsonResponse(data=data)

@api_view(['GET'])
@permission_classes([permissions.IsAuthenticated])
def subscription_details(request):
    subscription_holder: CustomUser = request.user

    if not subscription_holder.has_active_subscription():
        data = {
            'error': 'No active subscription.'
        }
        return JsonResponse(data=data)

    active_subscription: Subscription = subscription_holder.active_stripe_subscription

    # To make it work without webhook in localhost
    active_subscription = djstripe.models.Subscription.sync_from_stripe_data(active_subscription.api_retrieve())

    data = {
        'friendly_payment_amount': get_friendly_currency_amount(
            active_subscription.plan.amount * active_subscription.quantity,
            active_subscription.plan.currency
        ),
        'quantity': active_subscription.quantity,
        'start_date': active_subscription.start_date.strftime('%B %d, %Y'),
        'current_period_end': active_subscription.current_period_end.strftime('%B %d, %Y'),
        'subscription_urls': _get_subscription_urls(subscription_holder),
    }
    return JsonResponse(data=data)

def _view_subscription(request, subscription_holder):
    """
    Show user's active subscription
    """
    assert subscription_holder.has_active_subscription()
    data = {
        'subscription': subscription_holder.active_stripe_subscription,
        'subscription_urls': _get_subscription_urls(subscription_holder),
        'friendly_payment_amount': get_friendly_currency_amount(
            subscription_holder.active_stripe_subscription.plan.amount,
            subscription_holder.active_stripe_subscription.plan.currency,
        ),
        'product': get_product_and_metadata_for_subscription(subscription_holder.active_stripe_subscription),
    }
    return JsonResponse(data=data)

@api_view(['GET'])
@permission_classes([permissions.IsAuthenticated])
def upgrade_subscription(request):
    subscription_holder: CustomUser = request.user

    teammate_product = get_product_with_metadata(TEAMMATE_PRODUCT)
    email_product = get_product_with_metadata(EMAIL_PRODUCT)

    data = {
        'teammate_product': teammate_product.to_dict(),
        'email_product': email_product.to_dict(),
        'subscription_urls': _get_subscription_urls(subscription_holder),
        'payment_metadata': _get_payment_metadata_from_request(request),
    }

    return JsonResponse(data=data)

@api_view(['POST'])
@permission_classes([permissions.IsAuthenticated])
def create_stripe_portal_session(request, subscription_holder=None):
    subscription_holder = subscription_holder if subscription_holder else request.user

    current_url = request.data['current_url']

    stripe.api_key = djstripe_settings.STRIPE_SECRET_KEY
    if not subscription_holder.subscription or not subscription_holder.subscription.customer:
        messages.error(request, _("Whoops, we couldn't find a subscription associated with your account!"))
        data = {
            'error': "Whoops, we couldn't find a subscription associated with your account!"
        }
        return JsonResponse(data=data)

    session = stripe.billing_portal.Session.create(
        customer=subscription_holder.subscription.customer.id,
        return_url=request.build_absolute_uri(current_url),
    )

    data = {
        'session_url': session.url
    }
    return JsonResponse(data=data)


import discord
import os
import pyscreenshot as ImageGrab
import pyautogui
import time
from PIL import Image
from datetime import datetime

def findScreen():
    #used to find the emulator's GUI and create an offset for screencapping / clicking methods
    #start = pyautogui.locateCenterOnScreen('C:\\Users\\aritter\\Pictures\\upper screen.png')
    #print(start)
    #topFind = pyautogui.locateOnScreen('C:\\Users\\aritter\\Pictures\\upper screen.png', grayscale=True, confidence=.5)
    #botFind = pyautogui.locateOnScreen('C:\\Users\\aritter\\Pictures\\lower screen.png', confidence=.5)
    #print(topFind)
    #print(botFind)
    print("looking for screen")
    fileFind = pyautogui.locateOnScreen('D:\\EO\\yggdroid\\assets\\citrafileanchor.png', grayscale=False, confidence=.7)
    print(fileFind)
    xCitra, yCitra = pyautogui.locateCenterOnScreen('D:\\EO\\yggdroid\\assets\\fruitanchor.png')
    pyautogui.moveTo(xCitra, yCitra)
    #pyautogui.click(x, y)
    #print(topFind(top))
    #pyautogui.moveTo(fileFind)#Moves the mouse to the coordinates of the image
    #fileFind.show()
    return (xCitra, yCitra)

def topScreen():
    #grabs the top 3DS screen
    #TODO: dynamic variables
    citraLoc = findScreen()
    #topScreen = ImageGrab.grab(bbox=((citraLoc[0]-3), (citraLoc[1]+41), (citraLoc[0]+565), (citraLoc[1]+378)))
    topScreen = ImageGrab.grab(bbox=(0, 208, 1066, 847))
    return topScreen

def bottomScreen():
    #grabs the bottom 3DS screen
    #TODO: dynamic variables
    citraLoc = findScreen()
    #bottomScreen = ImageGrab.grab(bbox=((citraLoc[0]+59), (citraLoc[1]+379), (citraLoc[0]+509), (citraLoc[1]+716)))
    bottomScreen = ImageGrab.grab(bbox=(1067, 208, 1919, 847))
    return bottomScreen

def bothScreen():
    #grabs both screens, stitches then stitches them together
    topSc = topScreen()
    botSc = bottomScreen()
    topWd, topHt = topSc.size
    botWd, botHt = botSc.size
    #print(width)
    #print(height)
    bothScreen = Image.new('RGB', (topWd,(topHt+botHt)))
    bothScreen.paste(topSc)
    botOffset = (topWd/2) - (botWd/2)
    placementWBot = (1597-1119)/2
    bothScreen.paste(botSc, (round(botOffset), (topHt)))
    #bothScreen.paste(botSc, (x_offset, topWd/2), (y_offset, topHt))
    #bothScreen.show()
    return bothScreen

def makeFile():
    inputsList = ["up", "down", "left", "right", "a", "b", "x", "y", "start", "tapscreen", "dragscreen", "showTop", "showBottom", "showBoth", "write", "confirm"]
    gamesList = ["EO4", "EOV", "EOX", "EOU", "EOU2"]
    counter = 1
    counter1 = 0
    #winner = vote
    print(os.getcwd())
    #filePath = (os.path.join(os.getcwd(), "buttonLog" + winner + ".xlsx")
    filePath = (os.path.join(os.getcwd(), "buttonUserLog.xlsx"))
    if not os.path.exists('D:\\EO\\yggdroid\\buttonUserLog.xlsx'):
        workbook = xlsxwriter.Workbook(filePath)
        for game in gamesList:
            worksheet = workbook.add_worksheet(game)
            #counter1+=1
            for input in inputsList:
                worksheet.write(0, counter, (inputsList[(counter-1)]))
                print("Putting " + str(inputsList[(counter-1)]) + " in coloumn " + str(counter))
                counter+=1
            counter=1
        workbook.close()

class MyClient(discord.Client):
    async def on_ready(self):
        print('Logged in as')
        print(self.user.name)
        print(self.user.id)
        print('------')
    async def on_message(self, message):
        print(str(message.channel))
        #inputsList = ["up", "up_arrow", "down", "down_arrow", "left", "left_arrow", "right", "right_arrow", "a", "a_button", "b", "b_button", "x", "x_button", "y", "y_button", "start", "start_button", "tapscreen", "click", "dragscreen", "click"]
        #buttonPresses = ["up", "up_arrow", "down", "down_arrow", "left", "left_arrow", "right", "right_arrow", "a", "a_button", "b", "b_button", "x", "x_button", "y", "y_button", "start", "start_button", "tapscreen", "click", "dragscreen", "click"]
        inputsList = ["up", "down", "left", "right", "a", "b", "x", "y", "start", "select", "rb", "lb", "tapscreen", "dragscreen", "showtop", "showbottom", "showboth", "findscreen", "write", "confirm", "backspace"]
        #               0       1       2       3     4    5    6    7        8         9    10    11          12            13         14            15          16            17
        #buttonPresses = ["up_arrow","down_arrow","left_arrow","right_arrow","a_button","b_button","x_button","y_button","start_button","click","click"]
        buttonPresses = ["T", "G", "F", "H", "A", "S", "Z", "X", "M", "N", "W", "Q"]
        buttonLocations = ["1", "1130", "430","2", "1190", "430","3", "1260", "430","4", "1330", "430","5", "1390", "430","6", "1460", "430","7", "1530", "430","8", "1590", "430","9", "1660", "430","0", "1730", "430","-", "1790", "430","~", "1860", "430","q", "1160", "510","w", "1230", "510","e", "1290", "510","r", "1360", "510","t", "1430", "510","y", "1490", "510","u", "1560", "510","i", "1630", "510","o", "1690", "510","p", "1760", "510","a", "1130", "560","s", "1190", "560","d", "1260", "560","f", "1330", "560","g", "1390", "560","h", "1460", "560","j", "1530", "560","k", "1590", "560","l", "1660", "560",";", "1730", "560",":", "1790", "560","z", "1230", "630","x", "1290", "630","c", "1360", "630","v", "1430", "630","b", "1490", "630","n", "1560", "630","m", "1630", "630",",", "1690", "630",".", "1760", "630","[", "1260", "690","]", "1330", "690"," ", "1560", "690","!", "1790", "690","?", "1860", "690", "confirm", "1490", "790", "backspace", "1860", "510"]
        if message.author.id == self.user.id:
            return
        else:
            print("going into if")
            if str(message.channel) == "deep_city" or "report-channel-test":
                if message.content.casefold().startswith('~!setrole'):
                    requestedRole = message.content.casefold().split('~!setrole')[1:][0].lstrip()
                    selectedRole = list(filter(lambda role: role.name.casefold() == requestedRole.casefold(), message.guild.roles))[0]
                    print(selectedRole)
                    try:
                        await message.author.add_roles(selectedRole)
                        await message.channel.send('Hi ' + str(message.author.name) + '! I have added the role ' + str(selectedRole) + ' for you. '.format(message))
                    except Exception as e:
                        await message.channel.send('Sorry ' + str(message.author.name) + '! I wasn\'t able to set your role. Please reach out to the mod team so they can fix this.'.format(message))
                elif message.content.casefold().startswith('~!removerole'):
                    requestedRole = message.content.casefold().split('~!removerole')[1:][0].lstrip()
                    selectedRole = list(filter(lambda role: role.name.casefold() == requestedRole.casefold(), message.guild.roles))[0]
                    print(selectedRole)
                    try:
                        await message.author.remove_roles(selectedRole)
                        await message.channel.send('Hi ' + str(message.author.name) + '! I have removed the role ' + str(selectedRole) + ' for you. '.format(message))
                    except Exception as e:
                        await message.channel.send('Sorry ' + str(message.author.name) + '! I wasn\'t able to remove your role. Please reach out to the mod team so they can fix this.'.format(message))
                elif message.content.casefold().startswith('~!listroles'):
                    roleList = message.guild.roles
                    listFile = open("newFile.txt", 'w+')
                    for i in list(reversed(roleList)):
                        listFile.write(str(i) + '\n')
                    listFile = open("newFile.txt", "r")
                    toWrite = listFile.read()
                    toWrite = toWrite.split("beaned")[1]
                    listFile.close()
                    listFile = open("newFile.txt", "r")
                    sendFile = open("sendFile.txt", "w+")
                    toWrite = listFile.read()
                    toWrite = str(toWrite.split("beaned")[1])
                    toWrite = toWrite.replace("@everyone", "")
                    sendFile.write(toWrite)
                    listFile.close()
                    sendFile.close()
                    with open("sendFile.txt", "r") as sendFile:
                        try:
                            await message.channel.send(sendFile.read())
                        except Exception as e:
                            await message.channel.send('Sorry ' + str(message.author.name) + '! I wasn\'t able to list the roles. Please reach out to the mod team so they can fix this.'.format(message))
                    os.remove("sendFile.txt")
                    os.remove("newFile.txt")
            if (((str(message.channel.id)) == "685369497095503876") or ((str(message.channel.name)) == "yggtest")):
                    print(str(message))
                    print("found channel")
                    #if str(message).lower().strip().includes("") list.index(element)
                    command = str(message.content).lower().split()[0]
                    try:
                        commandAttr = str(message.content).split()[1:]
                        print("commandAttr is " + str(commandAttr))
                    except:
                        print("no attributes")
                    print("found command: " + command)
                    if any(usersInput in command for usersInput in inputsList):
                        print ("input in inputs list")
                        if command == ("buttons"):
                            buttonsShow = "```"
                            for each in inputsList[:12]:
                                buttonsShow = buttonsShow + each + ":" + buttonPresses[inputsList.index(each)] + "\n"
                            buttonsShow = buttonsShow + "```"
                            await message.channel.send(buttonsShow.format(message))
                        if inputsList.index(command) < 12:
                            print("input below 14")
                            #pyautogui.press(buttonPresses[inputsList.index(command)])
                            pyautogui.keyDown(buttonPresses[inputsList.index(command)])
                            time.sleep(.2)
                            print('up')
                            pyautogui.keyUp(buttonPresses[inputsList.index(command)])
                            print("input pressed was: " + buttonPresses[inputsList.index(command)])
                        else:
                            print(command + "not in inputsList")
                        if command.startswith("show"):
                            if command == ("showtop"):
                                showImage = topScreen()
                            elif command == ("showbottom"):
                                showImage = bottomScreen()
                            elif command == ("showboth"):
                                showImage = bothScreen()
                            now = datetime.now()
                            saveName = now.strftime("%d%m%Y%H%M%S") + ".png"
                            showImage.save(saveName)
                            await message.channel.send(file=discord.File(saveName))
                        #elif command.startswith("click"):
                        #    pyautogui.moveTo(100, 200, 2)
                        #    pyautogui.click()
                        #elif command.startswith("drag"):
                        #    pyautogui.moveTo(100, 200, 2)
                        #    pyautogui.dragTo(100, 200, button='left')
                        #elif command == ("findscreen"):
                        #    findScreen()
                        else:
                            print("couldn't find in second block")

                        '''elif not str(message.channel) == "deep_city":
                            if str(message.author.id) == "an":
                                print("in if 1")
                                if len(message.attachments) > 0:
                                    print("in if 2")
                                    await message.channel.send('<:eN:eID>')
                                    print("in after await")'''
                        print("check startWrite")
                        if command.startswith("write"):
                            print("trying split")
                            #command = commandAttr.split()
                            '''try:
                                command = command.split("write ")[1]
                                print("split space")
                            except:
                                try:
                                    print(command)
                                    command = command.split("write")[1]
                                    print("split no space")
                                    print(command)
                                except:
                                    print("couldn't split write")'''
                            print("check len")
                            if len(commandAttr) < 8:
                                print("len good, " + str(len(commandAttr)))
                                print(commandAttr)
                                print("going into char")
                                #newList =
                                for item in commandAttr:
                                    for char in item:
                                        print(char)
                                        if char.isupper():
                                            #pyautogui.moveTo(buttonLocations.index(command)+1, buttonLocations.index(command)+2)
                                            #[inputsList.index(each))
                                            #print("char is upper")
                                            whereis = str(buttonLocations.index(str(char.lower())))
                                            xLoc = (buttonLocations[int(whereis)+1])
                                            yLoc = (buttonLocations[int(whereis)+2])
                                            #print("char location: x" + ((buttonLocations[int(whereis)+1]) + " y" + (buttonLocations[int(whereis)+2])))
                                            print("Pressing SHIFT to UPPER")
                                            pyautogui.moveTo(x=1160, y=690)
                                            #pyautogui.click(clicks=2)
                                            pyautogui.mouseDown(); pyautogui.mouseUp()
                                            time.sleep(.3)
                                            print("Pressed SHIFT")
                                            #print("In Upper")
                                            #print("Char: " + char + "\nxLoc: " + xLoc + "\nyLoc: " + yLoc)
                                            pyautogui.moveTo(x=int(xLoc), y=int(yLoc))
                                            #pyautogui.click()
                                            pyautogui.mouseDown(); pyautogui.mouseUp()
                                            #pyautogui.mouseUp()
                                            time.sleep(.3)
                                            print("Pressing SHIFT to capitalize")
                                            '''pyautogui.moveTo(x=1160, y=690)
                                            #pyautogui.click(clicks=2)
                                            pyautogui.mouseDown(); pyautogui.mouseUp()
                                            #pyautogui.mouseUp()
                                            time.sleep(.5)
                                            print("Pressed SHIFT to LOWER")'''
                                        elif char.islower():
                                            #print("char is lower")
                                            whereis = str(buttonLocations.index(str(char.lower())))
                                            xLoc = (buttonLocations[int(whereis)+1])
                                            yLoc = (buttonLocations[int(whereis)+2])
                                            #print("In Lower")
                                            #print("Char: " + char + "\nxLoc: " + xLoc + "\nyLoc: " + yLoc)
                                            pyautogui.moveTo(x=int(xLoc), y=int(yLoc))
                                            pyautogui.mouseDown()
                                            pyautogui.mouseUp()
                                        else:
                                            #print("char is symbol")
                                            whereis = str(buttonLocations.index(str(char.lower())))
                                            xLoc = (buttonLocations[int(whereis)+1])
                                            yLoc = (buttonLocations[int(whereis)+2])
                                            #print("Symbol")
                                            pyautogui.moveTo(x=int(xLoc), y=int(yLoc))
                                            pyautogui.mouseDown()
                                            pyautogui.mouseUp()
                                        time.sleep(.1)
                                        #print("MoveTo")
                                        #print("Char: " + char + "\nxLoc: " + xLoc + "\nyLoc: " + yLoc)
                                        #print(command)
                            else:
                                print("Max name length is 8")
                        else:
                            print("didn't begin with write")
                        if command == "confirm":
                            whereis = str(buttonLocations.index("confirm"))
                            xLoc = (buttonLocations[int(whereis)+1])
                            yLoc = (buttonLocations[int(whereis)+2])
                            pyautogui.moveTo(x=int(xLoc), y=int(yLoc))
                            pyautogui.mouseDown()
                            pyautogui.mouseUp()
                        if command == "backspace":
                            whereis = str(buttonLocations.index("backspace"))
                            xLoc = (buttonLocations[int(whereis)+1])
                            yLoc = (buttonLocations[int(whereis)+2])
                            pyautogui.moveTo(x=int(xLoc), y=int(yLoc))
                            pyautogui.mouseDown()
                            pyautogui.mouseUp()
            print("no matches found")
            #print(str(message.channel.id))
client = MyClient()
client.run('NTMxNjE4NjEwMzQzNDQ0NTEy.XmIdBA.B5v1GO2g0mmvoAg-pK_P1z08xRM')

#    if inputsList.index(command) < 14:
#        print("yes")
#    elif inputsList.index(command) >= 14:
#        print("maybe")

#selectedRole is the value we want
#list
#filtering
#lambda role doesn't equal anything, declaring name of argument
#current item in the list turns into the current item in the list


# -*- coding: utf-8 -*-
"""
Created on Wed Feb 11 09:34:06 2015

@author: Admin
"""
import logging
import sys

def add_logging_handler(formatter, handler, name):

    logger = logging.getLogger(name)
    handler.setLevel(logging.DEBUG)
    handler.setFormatter(formatter)
    logger.addHandler(handler)

def config_logging(logging_dict, logging_format):
    name = logging_dict["name"]
    logger = logging.getLogger(name)

    formatter = logging.Formatter(logging_format)

    add_logging_handler(formatter, logging.StreamHandler(), name)
    logger.setLevel(logging_dict["logging_level"])

    add_logging_handler(formatter, logging.FileHandler(logging_dict["name"]), name)
    return logger

def get_logging_data(logger_data):
    logging_levels_dict = {"INFO": logging.INFO,
                           "DEBUG": logging.DEBUG,
                           "WARNING": logging.WARNING,
                           "ERROR": logging.ERROR,
                           "CRITICAL": logging.CRITICAL
                           }
    logger_path = logger_data.get("path")
    logging_level = logger_data.get("level")
    if logging_level not in logging_levels_dict.keys():
        sys.stdout.write("logging level %s doesn't exist, choosing default INFO\n" % logging_level)
        logging_level = "INFO"

    logging_dict = {"name": logger_path,
                    "logging_level": logging_level}
    return logging_dict

def get_logger(logger_data, logging_format):
    logging_dict = get_logging_data(logger_data)
    return config_logging(logging_dict, logging_format)


# encoding: utf-8
# Copyright (c) 2017 Mahdi bahri
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

import csv
import re
import json
contacts = "contacts.csv" # google contacts csv here exemple : contacts.csv

csvfile = open(contacts, 'r')
#get emails by columns : "E-mail Address" , "E-mail 2 Address" and "E-mail 3 Address"
columns = ("E-mail Address","E-mail 2 Address","E-mail 3 Address")
#read csv
csv = csv.DictReader( csvfile, columns)
id = 0
lists = []
for i in csv:
	id= id+1
	for d in i:
		try:
			lists.append(i[d][11])
		except :
			pass
ds=[]
for a in lists:
	#check email format
	EMAIL_REGEX = re.compile(r"[^@]+@[^@]+\.[^@]+")
	if  EMAIL_REGEX.match(a):
		ds.append(a)
#write to output file as json
with open('contact.json','a')as fs:
		json.dump(ds, fs)


"""A conversion module for googletrans"""
from __future__ import print_function
import re
import json

from googletrans.constants import DEFAULT_API_KEY

def build_params(src, dest, token, fmt, **kwargs) -> dict:
    return {
        'client': 'te_lib',
        'sl': src,
        'tl': dest,
        'tk': token,
        'format': fmt,
        'v': '1.0',
        'key': DEFAULT_API_KEY,
        **kwargs,
    }

def legacy_format_json(original):
    # save state
    states = []
    text = original

    # save position for double-quoted texts
    for i, pos in enumerate(re.finditer('"', text)):
        # pos.start() is a double-quote
        p = pos.start() + 1
        if i % 2 == 0:
            nxt = text.find('"', p)
            states.append((p, text[p:nxt]))

    # replace all weired characters in text
    while text.find(',,') > -1:
        text = text.replace(',,', ',null,')
    while text.find('[,') > -1:
        text = text.replace('[,', '[null,')

    # recover state
    for i, pos in enumerate(re.finditer('"', text)):
        p = pos.start() + 1
        if i % 2 == 0:
            j = int(i / 2)
            nxt = text.find('"', p)
            # replacing a portion of a string
            # use slicing to extract those parts of the original string to be kept
            text = text[:p] + states[j][1] + text[nxt:]

    converted = json.loads(text)
    return converted

def get_items(dict_object):
    for key in dict_object:
        yield key, dict_object[key]

def format_json(original):
    try:
        converted = json.loads(original)
    except ValueError:
        converted = legacy_format_json(original)

    return converted

def rshift(val, n):
    """python port for '>>>'(right shift with padding)
    """
    return (val % 0x100000000) >> n


# Author: F. Alex Wolf (http://falexwolf.de)
"""Logging and Profiling
"""

import os
import time
import datetime
from . import settings as sett

verbosity_levels_from_strings = {
    'error': 0,
    'warn': 1,
    'info': 2,
    'hint': 3,
}

def m(*msg, v='info', t=False, m=False, r=False, end='\n'):
    """Write message to log output.

    Log output defaults to standard output but can be set to a file
    by setting `sc.sett.log_file = 'mylogfile.txt'`.

    v/verbosity : {'error', 'warn', 'info', 'hint'} or int, (default: 'info')
        0/'error', 1/'warn', 2/'info', 3/'hint' or integer 4.
    t/timing : bool, optional (default: False)
        Print timing information.
    m/memory : bool, optional (default: Faulse)
        Print memory information.
    r/reset : bool, optional (default: False)
        Reset timing and memory measurement. Is automatically reset
        when passing one of t or m.
    end : str (default: '\n')
        As in python builtin print function.
    """
    if isinstance(v, str):
        v = verbosity_levels_from_strings[v]
    if isinstance(sett.verbosity, str):
        global_v = verbosity_levels_from_strings[sett.verbosity]
    else:
        global_v = sett.verbosity
    if v == 3:  # insert "--> " before hints
        msg = ('-->',) + msg
    if v >= 4:
        msg = ('   ',) + msg
    if v <= global_v:
        if not t and not m and len(msg) > 0:
            sett.mi(*msg, end=end)
        if r:
            sett._previous_memory_usage, _ = get_memory_usage()
            sett._previous_time = time.time()
        if t:
            elapsed = get_passed_time()
            msg = msg + ('({})'.format(sett._sec_to_str(elapsed)),)
            sett.mi(*msg, end=end)
        if m:
            sett.mi(format_memory_usage(get_memory_usage()), msg='' if t else msg, end=end)

def get_passed_time():
    now = time.time()
    elapsed = now - sett._previous_time
    sett._previous_time = now
    return elapsed

def get_memory_usage():
    import psutil
    process = psutil.Process(os.getpid())
    meminfo_attr = ('memory_info' if hasattr(process, 'memory_info')
                    else 'get_memory_info')
    mem = getattr(process, meminfo_attr)()[0] / 2**30  # output in GB
    mem_diff = mem
    if sett._previous_memory_usage != -1:
        mem_diff = mem - sett._previous_memory_usage
    sett._previous_memory_usage = mem
    return mem, mem_diff

def format_memory_usage(mem_usage, msg='', newline=False):
    mem, diff = mem_usage
    string = (('\n' if newline else '')
              + msg + (' \n... ' if msg != '' else '')
              + 'Memory usage: current {:.2f} GB, difference {:+.2f} GB'
              .format(mem, diff))
    return string

def print_memory_usage(msg='', newline=False):
    string = format_memory_usage(get_memory_usage(), msg, newline)
    sett.mi(string)

def print_version_and_date():
    from . import __version__
    sett.mi('Running Scanpy version', __version__, 'on {}.'.format(get_date()))

def get_date():
    return datetime.datetime.now().strftime("%Y-%m-%d %H:%M")


from bs4 import BeautifulSoup
from urllib.request import urlopen
import pandas as pd

################### 코스피:1 , 코스닥:2 #########################
def get_code(num):
    response = urlopen('https://www.sedaily.com/Stock/Quote?type='+str(num))
    soup = BeautifulSoup(response, 'html.parser')

    all_table = soup.find_all('div', {'class': 'table'})

    code_dict = {}
    for thead in all_table:
        dl = thead.find('dl', {'class': 'thead'})

        dt = dl.find('dt')
        fieldName = dt.text

        tbody = thead.find_all('dl', {'class': 'tbody'})

        for dl in tbody:
            name = dl.find('dt').get_text()
            dd = dl.find('dd')
            code = dd.get('id').replace('dd_Item_', '')

            code_dict[code] = [name, fieldName]
    return code_dict

df_kospi_present = pd.DataFrame(get_code(1)).T

df_kospi_present.columns = ['종목명', '업종']

df_kospi_present.to_csv("kospi_code.csv")

df_kosdaq_present = pd.DataFrame(get_code(2)).T

df_kosdaq_present.columns = ['종목명', '업종']

df_kosdaq_present.to_csv("kosdaq_code.csv")


"""
Project: ChordNet
Author: Gabriel Abrantes
Email: gabrantes99@gmail.com
Date: 7/2/2019
Filename: aug.py
Description:
    Contains functions for augmenting the dataeset.
"""

from utils.chorus.satb import Satb
from utils.utils import one_hot
import numpy as np

def augment(progression: list) -> list:
    """
    `Augment` a progression by tranposing it to a new key.

    Args:
        progression: a list representing one line from the dataset
                    (with scaled chords and one-hot tuples)

    Returns:
        A list representing the new, tranposed progression
        (still with scaled chords and one-hot tuples).
    """
    assert len(progression) == 16

    satb = Satb()
    lo, hi = satb.transpose_range(satb.unscale(progression[5:9]), satb.unscale(progression[12:16]))
    shift = np.random.randint(lo, hi+1)

    new_progression = progression[:]

    # tonic (key signature)
    cur_key = new_progression[0].index(1)
    new_key = (cur_key + shift) % 12
    new_progression[0] = tuple(one_hot(new_key, 12))

    for j in range(5, 9):  # cur chord
        new_progression[j] += shift
    for j in range(12, 16):  # next chord
        new_progression[j] += shift

    return new_progression


#!/usr/binY/env python

## Program:   VMTK
## Module:    $RCSfile: vmtkpointselector.py,v $
## Language:  Python
## Date:      $Date: 2006/07/17 09:52:56 $
## Version:   $Revision: 1.20 $

##   Copyright (c) Luca Antiga, David Steinman. All rights reserved.
##   See LICENCE file for details.

##      This software is distributed WITHOUT ANY WARRANTY; without even
##      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
##      PURPOSE.  See the above copyright notices for more information.

import vtk
import sys
from os import path

import vtkvmtk
import vmtkrenderer
import pypes

vmtkpointselector = 'vmtkPointselector'

class vmtkSeedSelector():

    def __init__(self):
        self._Surface = None
        self._SeedIds = None
        self._SourceSeedIds = vtk.vtkIdList()
        self._TargetSeedIds = vtk.vtkIdList()
        self.PrintError = None
        self.PrintLog = None
        self.InputText = None
        self.OutputText = None
        self.InputInfo = None

    def SetSurface(self,surface):
        self._Surface = surface

    def GetSurface(self):
        return self._Surface

    def GetSourceSeedIds(self):
        return self._SourceSeedIds

    def GetTargetSeedIds(self):
        return self._TargetSeedIds

    def Execute(self):
        pass

class vmtkPickPointSeedSelector(vmtkSeedSelector):

    def __init__(self):
        vmtkSeedSelector.__init__(self)
        self.PickedSeedIds = vtk.vtkIdList()
        self.PickedSeeds = vtk.vtkPolyData()
        self.vmtkRenderer = None
        self.OwnRenderer = 0
        self.Script = None

    def UndoCallback(self, obj):
        self.InitializeSeeds()
        self.PickedSeeds.Modified()
        self.vmtkRenderer.RenderWindow.Render()

    def PickCallback(self, obj):
        picker = vtk.vtkCellPicker()
        picker.SetTolerance(1E-4 * self._Surface.GetLength())
        eventPosition = self.vmtkRenderer.RenderWindowInteractor.GetEventPosition()
        result = picker.Pick(float(eventPosition[0]),float(eventPosition[1]),0.0,self.vmtkRenderer.Renderer)
        if result == 0:
            return
        pickPosition = picker.GetPickPosition()
        pickedCellPointIds = self._Surface.GetCell(picker.GetCellId()).GetPointIds()
        minDistance = 1E10
        pickedSeedId = -1
        for i in range(pickedCellPointIds.GetNumberOfIds()):
            distance = vtk.vtkMath.Distance2BetweenPoints(pickPosition,self._Surface.GetPoint(pickedCellPointIds.GetId(i)))
            if distance < minDistance:
                minDistance = distance
                pickedSeedId = pickedCellPointIds.GetId(i)
        if pickedSeedId == -1:
            pickedSeedId = pickedCellPointIds.GetId(0)
        self.PickedSeedIds.InsertNextId(pickedSeedId)
        point = self._Surface.GetPoint(pickedSeedId)
        self.PickedSeeds.GetPoints().InsertNextPoint(point)
        self.PickedSeeds.Modified()
        self.vmtkRenderer.RenderWindow.Render()

    def InitializeSeeds(self):
        self.PickedSeedIds.Initialize()
        self.PickedSeeds.Initialize()
        seedPoints = vtk.vtkPoints()
        self.PickedSeeds.SetPoints(seedPoints)

    def Execute(self):

        if (self._Surface == None):
            self.PrintError('vmtkPickPointSeedSelector Error: Surface not set.')
            return

        self._SourceSeedIds.Initialize()
        self._TargetSeedIds.Initialize()

        if not self.vmtkRenderer:
            self.vmtkRenderer = vmtkrenderer.vmtkRenderer()
            self.vmtkRenderer.Initialize()
            self.OwnRenderer = 1

        self.vmtkRenderer.RegisterScript(self.Script)

        glyphs = vtk.vtkGlyph3D()
        glyphSource = vtk.vtkSphereSource()
        glyphs.SetInput(self.PickedSeeds)
        glyphs.SetSource(glyphSource.GetOutput())
        glyphs.SetScaleModeToDataScalingOff()
        glyphs.SetScaleFactor(self._Surface.GetLength()*0.01)
        glyphMapper = vtk.vtkPolyDataMapper()
        glyphMapper.SetInput(glyphs.GetOutput())
        self.SeedActor = vtk.vtkActor()
        self.SeedActor.SetMapper(glyphMapper)
        self.SeedActor.GetProperty().SetColor(1.0,0.0,0.0)
        self.SeedActor.PickableOff()
        self.vmtkRenderer.Renderer.AddActor(self.SeedActor)

        ##self.vmtkRenderer.RenderWindowInteractor.AddObserver("KeyPressEvent", self.KeyPressed)
        self.vmtkRenderer.AddKeyBinding('u','Undo.',self.UndoCallback)
        self.vmtkRenderer.AddKeyBinding('space','Add points.',self.PickCallback)
        surfaceMapper = vtk.vtkPolyDataMapper()
        surfaceMapper.SetInput(self._Surface)
        surfaceMapper.ScalarVisibilityOff()
        surfaceActor = vtk.vtkActor()
        surfaceActor.SetMapper(surfaceMapper)
        surfaceActor.GetProperty().SetOpacity(1.0)

        self.vmtkRenderer.Renderer.AddActor(surfaceActor)

        self.InputInfo('Please position the mouse and press space to add source points, \'u\' to undo\n')

        any = 0
        while any == 0:
            self.InitializeSeeds()
            self.vmtkRenderer.Render()
            any = self.PickedSeedIds.GetNumberOfIds()
        self._SourceSeedIds.DeepCopy(self.PickedSeedIds)

        self.InputInfo('Please position the mouse and press space to add target points, \'u\' to undo\n')

        any = 0
        while any == 0:
            self.InitializeSeeds()
            self.vmtkRenderer.Render()
            any = self.PickedSeedIds.GetNumberOfIds()
        self._TargetSeedIds.DeepCopy(self.PickedSeedIds)

        if self.OwnRenderer:
            self.vmtkRenderer.Deallocate()

class vmtkNonManifoldSurfaceChecker(object):

    def __init__(self):

        self.Surface = 0

        self.NumberOfNonManifoldEdges = 0
        self.Report = 0
        self.NonManifoldEdgePointIds = vtk.vtkIdList()

        self.PrintError = None

    def Execute(self):

        if (self.Surface == 0):
            self.PrintError('NonManifoldSurfaceChecker error: Surface not set')
            return

        self.NonManifoldEdgesFound = 0
        self.Report = ''
        self.NonManifoldEdgePointIds.Initialize()

        neighborhoods = vtkvmtk.vtkvmtkNeighborhoods()
        neighborhoods.SetNeighborhoodTypeToPolyDataManifoldNeighborhood()
        neighborhoods.SetDataSet(self.Surface)
        neighborhoods.Build()

        neighborCellIds = vtk.vtkIdList()
        cellPointIds = vtk.vtkIdList()

        self.Surface.BuildCells()
        self.Surface.BuildLinks(0)
        self.Surface.Update()

        numberOfNonManifoldEdges = 0

        for i in range(neighborhoods.GetNumberOfNeighborhoods()):

            neighborhood = neighborhoods.GetNeighborhood(i)

            for j in range(neighborhood.GetNumberOfPoints()):

                neighborId = neighborhood.GetPointId(j)

                if (i<neighborId):

                    neighborCellIds.Initialize()
                    self.Surface.GetCellEdgeNeighbors(-1,i,neighborId,neighborCellIds)

                    if (neighborCellIds.GetNumberOfIds()>2):

                        numberOfNonManifoldEdges = numberOfNonManifoldEdges + 1

                        self.Report = self.Report +  "Non-manifold edge found" + str(i) + ' ' + str(neighborId) + '.\n'

                        self.NonManifoldEdgePointIds.InsertNextId(i)
                        self.NonManifoldEdgePointIds.InsertNextId(neighborId)

class vmtkPointselector(pypes.pypeScript):

    def __init__(self):

        pypes.pypeScript.__init__(self)

        self.Surface = None
        self.Output = None
        self.Centerlines = None
        self.SeedSelector = None
        self.SeedSelectorName = 'pickpoint'
        self.FlipNormals = 0
        self.CapDisplacement = 0.0
        self.RadiusArrayName = 'MaximumInscribedSphereRadius'
        self.CostFunction = '1/R'
        self.AppendEndPoints = 0
        self.CheckNonManifold = 0

        self.Resampling = 0
        self.ResamplingStepLength = 1.0
        self.SimplifyVoronoi = 0

        self.EikonalSolutionArrayName = 'EikonalSolution'
        self.EdgeArrayName = 'EdgeArray'
        self.EdgePCoordArrayName = 'EdgePCoordArray'
        self.CostFunctionArrayName = 'CostFunctionArray'

        self.UseTetGen = 0
        self.TetGenDetectInter = 1

        self.DelaunayTessellation = None
        self.VoronoiDiagram = None
        self.PoleIds = None

        self.DelaunayTolerance = 0.001

        self.SourceIds = []
        self.TargetIds = []
        self.SourcePoints = []
        self.TargetPoints = []

        self.vmtkRenderer = None
        self.OwnRenderer = 0

        self.SetScriptName('vmtkpointselector')
        self.SetScriptDoc('Choose points on a geometry that will be stored for later use')
        self.SetInputMembers([['Surface', 'i', 'vtkPolyData', 1, '',
                               'the input surface', 'vmtksurfacereader'],
                               ["Output", 'opath', 'str', 1, "", "Filepath to store points"]])
        self.SetOutputMembers([['Centerlines','o','vtkPolyData',1,'','the output centerlines',
                                'vmtksurfacewriter']])

    def PrintProgress(self,obj,event):
        self.OutputProgress(obj.GetProgress(),10)

    def Execute(self):
        self.SeedSelectorName = "pickpoint"

        if self.Surface == None:
            self.PrintError('Error: No input surface.')

        if self.CheckNonManifold:
            self.PrintLog('NonManifold check.')
            nonManifoldChecker = vmtkNonManifoldSurfaceChecker()
            nonManifoldChecker.Surface = self.Surface
            nonManifoldChecker.PrintError = self.PrintError
            nonManifoldChecker.Execute()

            if (nonManifoldChecker.NumberOfNonManifoldEdges > 0):
                self.PrintLog(nonManifoldChecker.Report)
                return

        self.vmtkRenderer = vmtkrenderer.vmtkRenderer()
        self.vmtkRenderer.Initialize()
        self.OwnRenderer = 1

        self.PrintLog('Cleaning surface.')
        surfaceCleaner = vtk.vtkCleanPolyData()
        surfaceCleaner.SetInput(self.Surface)
        surfaceCleaner.Update()

        self.PrintLog('Triangulating surface.')
        surfaceTriangulator = vtk.vtkTriangleFilter()
        surfaceTriangulator.SetInput(surfaceCleaner.GetOutput())
        surfaceTriangulator.PassLinesOff()
        surfaceTriangulator.PassVertsOff()
        surfaceTriangulator.Update()

        self.PrintLog('Capping surface.')
        surfaceCapper = vtkvmtk.vtkvmtkCapPolyData()
        surfaceCapper.SetInput(surfaceTriangulator.GetOutput())
        surfaceCapper.SetDisplacement(self.CapDisplacement)
        surfaceCapper.SetInPlaneDisplacement(self.CapDisplacement)
        surfaceCapper.Update()
        centerlineInputSurface = surfaceCapper.GetOutput()
        capCenterIds = surfaceCapper.GetCapCenterIds()

        self.SeedSelector = vmtkPickPointSeedSelector()
        self.SeedSelector.vmtkRenderer = self.vmtkRenderer
        self.SeedSelector.Script = self

        self.SeedSelector.SetSurface(centerlineInputSurface)
        self.SeedSelector.InputInfo = self.InputInfo
        self.SeedSelector.InputText = self.InputText
        self.SeedSelector.OutputText = self.OutputText
        self.SeedSelector.PrintError = self.PrintError
        self.SeedSelector.PrintLog = self.PrintLog
        self.SeedSelector.Execute()

        inletSeedIds = self.SeedSelector.GetSourceSeedIds()
        outletSeedIds = self.SeedSelector.GetTargetSeedIds()

        point_source = []
        points_target = []
        s = ""
        text_target = "target%s: %s\n"
        text_source = "source: %s\n"

        for i in range(inletSeedIds.GetNumberOfIds()):
            point_source.append(centerlineInputSurface.GetPoint(inletSeedIds.GetId(i)))
            s += text_source % (str(point_source[-1]))

        for i in range(outletSeedIds.GetNumberOfIds()):
            points_target.append(centerlineInputSurface.GetPoint(outletSeedIds.GetId(i)))
            s += text_target % (i, points_target[-1])

        f = open(path.join(self.Output, "points"), "w")
        f.write(s)
        f.close()

if __name__=='__main__':
    main = pypes.pypeMain()
    main.Arguments = sys.argv
    main.Execute()