import sys
import os
import time

from ROOT import TFile, TH1, TDirectory
from ROOT import TROOT
import ROOT

from Uncertainty import Uncertainty
from Process import Process
from Datacard import Datacard
from ProcessCollection import ProcessCollection
from style import setStyle
from drawPlot_martina import drawPlot
from drawPlot_martina import writeTables_sumErrors

def buildHistogramDictionary( root_file_path ):
    root_file = TFile( root_file_path )
    histogram_dict = {}
    for entry in root_file.GetListOfKeys():
        name = entry.GetName()
        hist = root_file.Get( name )
        hist.SetDirectory( 0 )
        if isinstance( hist, TH1 ) :
            histogram_dict[ name ] = hist
    return histogram_dict

if __name__ == '__main__':

    #set plotting style
    style = setStyle()

    if len( sys.argv ) > 1:
        base_card_path = sys.argv[1]
    else:
        print( 'Hello Martina' )
        print( '----- Didar is typing---- ' )
        time.sleep( 5 )
        print( 'Himmmmmmmmmmm' )
        sys.exit()

    if len( sys.argv ) > 2:
        base_card_path2 = sys.argv[2]
    else:
        print( 'Hello Martina' )
        print( '----- Didar is typing---- ' )
        time.sleep( 5 )
        print( 'Himmmmmmmmmmm' )
        sys.exit()
    if len( sys.argv ) > 3:
        base_card_path3 = sys.argv[3]
    else:
        print( 'Hello Martina' )
        print( '----- Didar is typing---- ' )
        time.sleep( 5 )
        print( 'Himmmmmmmmmmm' )
        sys.exit()
    if len( sys.argv ) > 4:
        base_card_path4 = sys.argv[4]
    else:
        print( 'Hello Martina' )
        print( '----- Didar is typing---- ' )
        time.sleep( 5 )
        print( 'Himmmmmmmmmmm' )
        sys.exit()

    if len( sys.argv ) > 5:
        flav = [ sys.argv[5] ]
    else:
        flav = ['muon', 'ele']

    if len( sys.argv ) > 6:
        plot = [ sys.argv[6] ]
    else:
        plot = ['SR', 'M', 'D','M3' ]

    if len( sys.argv ) > 7:
        mass1 = [ sys.argv[7] ]
    else:
        mass1 = ['5GeV']
    if len( sys.argv ) > 8:
        mass2 = [ sys.argv[8] ]
    else:
        mass2 = ['5GeV']
    if len( sys.argv ) > 9:
        mass3 = [ sys.argv[9] ]
    else:
        mass3 = ['5GeV']

    if len( sys.argv ) > 10:
        v1 = [ sys.argv[10] ]
    else:
        v1 = ['01']
    if len( sys.argv ) > 11:
        v2 = [ sys.argv[11] ]
    else:
        v2 = ['01']
    if len( sys.argv ) > 12:
        v3 = [ sys.argv[12] ]
    else:
        v3 = ['01']

    if len( sys.argv ) > 13:
        years = [ sys.argv[13] ]
    else:
        years = ['16', '17', '18' ]

    if flav[0] == 'muon':
        base_card_path = base_card_path.replace( '_mu_Dirac_muo', '_mu_Dirac_muo' )
        base_card_path2 = base_card_path2.replace( '_mu_Dirac_muo', '_mu_Dirac_muo' )
        base_card_path3 = base_card_path3.replace( '_mu_Dirac_muo', '_mu_Dirac_muo' )
        base_card_path4 = base_card_path4.replace( '_mu_Dirac_muo', '_mu_Dirac_muo' )
    if flav[0] == 'ele':
        base_card_path = base_card_path.replace( '_mu_Dirac_muo', '_e_Dirac_ele' )
        base_card_path2 = base_card_path2.replace( '_mu_Dirac_muo', '_e_Dirac_ele' )
        base_card_path3 = base_card_path3.replace( '_mu_Dirac_muo', '_e_Dirac_ele' )
        base_card_path4 = base_card_path4.replace( '_mu_Dirac_muo', '_e_Dirac_ele' )

    if plot[0] == 'M':
        base_card_path = base_card_path.replace( '_datacard', '_mass_datacard' )
        base_card_path2 = base_card_path2.replace( '_datacard', '_mass_datacard' )
        base_card_path3 = base_card_path3.replace( '_datacard', '_mass_datacard' )
        base_card_path4 = base_card_path4.replace( '_datacard', '_mass_datacard' )
    elif plot[0] == 'D':
        base_card_path = base_card_path.replace( '_datacard', '_disp_datacard' )
        base_card_path2 = base_card_path2.replace( '_datacard', '_disp_datacard' )
        base_card_path3 = base_card_path3.replace( '_datacard', '_disp_datacard' )
        base_card_path4 = base_card_path4.replace( '_datacard', '_disp_datacard' )
    elif plot[0] == 'M3':
        base_card_path = base_card_path.replace( '_datacard', '_mass3_datacard' )
        base_card_path2 = base_card_path2.replace( '_datacard', '_mass3_datacard' )
        base_card_path3 = base_card_path3.replace( '_datacard', '_mass3_datacard' )
        base_card_path4 = base_card_path4.replace( '_datacard', '_mass3_datacard' )
    elif plot[0] == 'SR':
        base_card_path = base_card_path.replace( '_datacard', '_datacard' )
        base_card_path2 = base_card_path2.replace( '_datacard', '_datacard' )
        base_card_path3 = base_card_path3.replace( '_datacard', '_datacard' )
        base_card_path4 = base_card_path4.replace( '_datacard', '_datacard' )

    datacard_paths = [ '{}_{}.txt'.format( base_card_path, y ) for y in years ]
    datacards = [ Datacard( path ) for path in datacard_paths ]
    #additional signal sample to add to the plot
    datacard_paths2 = [ '{}_{}.txt'.format( base_card_path2, y ) for y in years ]
    datacards2 = [ Datacard( path ) for path in datacard_paths2 ]
    datacard_paths3 = [ '{}_{}.txt'.format( base_card_path3, y ) for y in years ]
    datacards3 = [ Datacard( path ) for path in datacard_paths3 ]
    datacard_paths4 = [ '{}_{}.txt'.format( base_card_path4, y ) for y in years ]
    datacards4 = [ Datacard( path ) for path in datacard_paths4 ]

##################### central one! ##########################
    processCollections = []
    total_data = None
    for i, card in enumerate( datacards ):
        #build the backgrounds
        histogram_dict = buildHistogramDictionary( card.shapeFilePath() )
        process_list = []
        for p in card.processNames():
            process_list.append( Process( p, histogram_dict, card, 'signal' in p ) )
        processCollections.append( ProcessCollection( process_list ) )
        #merge the data
        if total_data is None:
            total_data = histogram_dict[ 'data_obs' ]
        else :
            total_data.Add( histogram_dict[ 'data_obs' ] )
    total_process_collection = processCollections[0]
    for col in processCollections[1:]:
        total_process_collection += col
############ 2.3.4 ##############
    processCollections2 = []
    for i, card2 in enumerate( datacards2 ):
        #build the backgrounds
        histogram_dict2 = buildHistogramDictionary( card2.shapeFilePath() )
        process_list2 = []
        for p in card2.processNames():
            process_list2.append( Process( p, histogram_dict2, card2, 'signal' in p ) )
        processCollections2.append( ProcessCollection( process_list2 ) )
    total_process_collection2 = processCollections2[0]
    for col in processCollections2[1:]:
        total_process_collection2 += col

    processCollections3 = []
    for i, card3 in enumerate( datacards3 ):
        #build the backgrounds
        histogram_dict3 = buildHistogramDictionary( card3.shapeFilePath() )
        process_list3 = []
        for p in card3.processNames():
            process_list3.append( Process( p, histogram_dict3, card3, 'signal' in p ) )
        processCollections3.append( ProcessCollection( process_list3 ) )
    total_process_collection3 = processCollections3[0]
    for col in processCollections3[1:]:
        total_process_collection3 += col

    processCollections4 = []
    for i, card4 in enumerate( datacards4 ):
        #build the backgrounds
        histogram_dict4 = buildHistogramDictionary( card4.shapeFilePath() )
        process_list4 = []
        for p in card4.processNames():
            process_list4.append( Process( p, histogram_dict4, card4, 'signal' in p ) )
        processCollections4.append( ProcessCollection( process_list4 ) )
    total_process_collection4 = processCollections4[0]
    for col in processCollections4[1:]:
        total_process_collection4 += col

   #correct plot label for each variable:
    if len( plot ) == 1:
        if plot[0] == 'SR':
            plot_label = 'SR'
        elif plot[0] == 'M':
            plot_label = 'massl2l3'
        elif plot[0] == 'D':
            plot_label = 'displacement'
        elif plot[0] == 'M3':
            plot_label = 'mass3'
        else:
            print( 'Himmmmmm, A-Z analysis, money plot, Illia runs everything in one afternoon' )
    else:
        print( 'Himmmmmm, A-Z analysis, money plot, Illia runs everything in one afternoon' )

    #correct plot label for each variable:
    if len( flav ) == 1:
        if flav[0] == 'muon':
            flav_label = 'muon'
        elif flav[0] == 'ele':
            flav_label = 'ele'
        else:
            print( 'Himmmmmm, A-Z analysis, money plot, Illia runs everything in one afternoon' )
    else:
        print( 'Himmmmmm, A-Z analysis, money plot, Illia runs everything in one afternoon' )

    #correct lumi label for each year:
    if len( years ) == 1:
        if years[0] == '16':
            lumi_label = '35.9 fb^{-1} (13 TeV)'
        elif years[0] == '17':
            lumi_label = '41.5 fb^{-1} (13 TeV)'
        elif years[0] == '18':
            lumi_label = '59.7 fb^{-1} (13 TeV)'
        else:
            print( 'Himmmmmm, A-Z analysis, money plot, Illia runs everything in one afternoon' )

    elif len( years ) == 3:
        lumi_label = '137 fb^{-1} (13 TeV)'

    else:
        print( 'Himmmmmm, A-Z analysis, money plot, Illia runs everything in one afternoon' )

    #correct signal legend:
    if len( mass1 ) == 1:
        mass1_label = mass1[0]
    else:
        print( 'no mass1' )
    if len( mass2 ) == 1:
        mass2_label = mass2[0]
    else:
        print( 'no mass2' )
    if len( mass3 ) == 1:
        mass3_label = mass3[0]
    else:
        print( 'no mass3' )
    if len( v1 ) == 1:
        v1_label = v1[0]
    else:
        print( 'no v1' )
    if len( v2 ) == 1:
        v2_label = v2[0]
    else:
        print( 'no v2' )
    if len( v3 ) == 1:
        v3_label = v3[0]
    else:
        print( 'no v3' )

    #plot_name
    year_name = years[0] if len( years ) == 1 else 'combined'
    #print 'pp   '+base_card_path

    base_card_path = base_card_path.replace( '.', 'p' )
    plot_name = os.path.basename( base_card_path ) + '_' + year_name + '_' + plot_label
    #print base_card_path
    #print plot_name

    colors = { 'nonpromptDF' : ROOT.kGreen, 'nonpromptSF' : ROOT.kGreen + 2, 'Xgamma' : ROOT.kViolet+1 }
    legend_names = { 'nonpromptDF' : 'nonprompt DF', 'nonpromptSF' : 'nonprompt SF', 'Xgamma' : 'conversions' }
    #legend_names = { 'DY' : 'DY', 'nonpromptDF' : 'nonprompt DF', 'nonpromptSF' : 'nonprompt SF', 'TTTX' : 'other', 'multiboson' : 'multiboson', 'Xgamma' : 'conversions' }
    #colors = { 'nonpromptDF' : ROOT.kGreen, 'nonpromptSF' : ROOT.kGreen + 2, 'TTTX' : ROOT.kRed-10, 'multiboson' : ROOT.kRed-10, 'Xgamma' : ROOT.kViolet+1 }

    #legend_names = { 'nonpromptDF' : 'nonprompt DF', 'nonpromptSF' : 'nonprompt SF', 'TTTX' : 'other', 'Xgamma' : 'conversions' }

    #new function to draw more than 1 signal

    drawPlot( total_data, total_process_collection,total_process_collection2,total_process_collection3, total_process_collection4, plot_name, colors, legend_names = legend_names, lumi_text = lumi_label, plot_axis= plot_label, flav_name = flav_label, mass1_name = mass1_label, mass2_name = mass2_label,mass3_name = mass3_label, v1_name = v1_label, v2_name = v2_label,v3_name = v3_label)

    if plot_label == 'SR': writeTables_sumErrors( total_data, total_process_collection,total_process_collection2,total_process_collection3, total_process_collection4, plot_name, plot_axis= plot_label, flav_name = flav_label, year_label = year_name, mass1_name = mass1_label, mass2_name = mass2_label,mass3_name = mass3_label, v1_name = v1_label, v2_name = v2_label,v3_name = v3_label)


import sqlite3
import requests
import json

#define connection
conn = sqlite3.connect('pokemon_y.db')
c = conn.cursor()

class User_Info:
    def __init__(self, username = None, level = None):
        self.username = username
        self.level = level

class Pokemon:
    def __init__(self, username = None, poke_name = None):
        self.username = username
        self.poke_name = poke_name

class Model:
    def __init__(self):
        pass

    def add_user_info(self, user_info): #add informaton to the userInfo table
        c.execute("""
            INSERT INTO userInfo (username, level) VALUES (?,?)
            """,
            (user_info.username, user_info.level)
        )
        conn.commit()
        c.close()

    def add_pokemon_info (self, pokeinfo): #add pokemon name to pokemon table
        get_species = requests.get("http://pokeapi.co/api/v2/pokemon/{x}".format(x=pokeinfo.poke_name))
        species_json = get_species.json()
        species = species_json['species']['name'] #get species name[12]

        get_habitat = requests.get("http://pokeapi.co/api/v2/pokemon-species/{x}".format(x=pokeinfo.poke_name))
        habitat_json = get_habitat.json()
        habitat = habitat_json['habitat']['name'] #get habitat name[13]
        c.execute("""
            INSERT INTO pokemon (username, poke_name, species_name, habitat_name) VALUES (?,?,?,?)
            """,
            (pokeinfo.username, pokeinfo.poke_name, species, habitat)
        )
        conn.commit() #save

        c.execute("""
            INSERT INTO species (poke_name, species_name, habitat_name) VALUES (?,?,?)
            """,
            (pokeinfo.poke_name, species, habitat)

        )
        conn.commit() #save

        c.execute("""
            INSERT INTO habitat (poke_name, poke_habitat, poke_species) VALUES (?,?,?)
            """,
            (pokeinfo.poke_name, habitat, species)
        )
        conn.commit() #save
        c.close()

    def add_pokemon_species (self, species):
        c.execute("""
            INSERT INTO species (poke_name, species_name, habitat_name) VALUES (?,?,?)
            """,
            (species.poke_name, species.species_name, species.habitat_name)
        )
        conn.commit() #save
        c.close()

    def add_pokemon_habitat (self, habitat):
        c.execute("""
            INSERT INTO habitat (poke_name, habitat_name, species_name) VALUES (?,?,?)
            """,
            (habitat.poke_name, habitat.habitat_name, habitat.species_name)
        )
        conn.commit() #save
        c.close()

    def read_from_userInfo(self, username): #show userInfo table
        c.execute("SELECT * FROM userInfo")
        [print(row) for row in c.fetchall()]
        conn.commit()
        c.close()

    def read_from_pokemon_by_user(self, username):
        c.execute("SELECT poke_name FROM pokemon where poke_name = ?", (username,))
        [print(row) for row in c.fetchall()]

    def read_from_poke_species_by_user(self, username):
        c.execute("SELECT species_name FROM pokemon where species_name = ?", (username,))
        [print(row) for row in c.fetchall()]

    def read_from_poke_habitat_by_user(self, username):
        c.execute("SELECT habitat_name FROM pokemon where habit_name = ?", (username,))
        c.execute("SELECT habitat_name FROM pokemon where habit_name = ?", (username,))
        [print(row) for row in c.fetchall()]

    def delete_user_table(self, deleteuser): #delete row where username = ?
        c.execute("DELETE FROM userInfo WHERE username = ?", (deleteuser,))
        [print(row) for row in c.fetchall()]
        conn.commit() #save
        c.close()

    def update_user_table(self, change_user): #change username
        c.execute("UPDATE userInfo SET username =? WHERE username ='bcho'", (change_user,))
        [print(row) for row in c.fetchall()]
        conn.commit() #save
        c.close()

    def species_count (self, species):
        c.execute("SELECT COUNT(*) FROM pokemon WHERE species = ?", (species,))
        [print(row) for row in c.fetchall()]
        conn.commit()

#c.close()
#conn.close()


"""Subscriptions forms."""

from django import forms
from django.urls import reverse
from django.utils.translation import gettext_lazy as _

from readthedocs.subscriptions.models import Plan

class PlanForm(forms.Form):

    """Form to create a subscription after the previous one has ended."""

    plan = forms.ChoiceField()

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['plan'].choices = [
            (plan.pk, f'{plan.name} (${plan.price})')
            for plan in Plan.objects.filter(published=True).order_by('price')
        ]
        pricing_page = reverse('pricing')
        self.fields['plan'].help_text = _(
            f'Check our pricing page '
            'for more information about each plan.'
        )


import pandas as pd

pd.set_option("display.max_columns",166)
from IPython import get_ipython
ipy = get_ipython()
if ipy is not None:
    ipy.run_line_magic('matplotlib', 'inline')
    ipy.run_line_magic('pylab', 'inline')
import matplotlib.pyplot as plt
plt.style.use('ggplot')

TabelaInfra = ["NU_ANO_CENSO","CO_UF","CO_MUNICIPIO","IN_SALA_PROFESSOR","IN_LABORATORIO_INFORMATICA",
                "IN_LABORATORIO_CIENCIAS","IN_QUADRA_ESPORTES_COBERTA","IN_QUADRA_ESPORTES_DESCOBERTA","IN_COZINHA","IN_BIBLIOTECA",
                "IN_AUDITORIO","IN_PATIO_COBERTO","IN_PATIO_DESCOBERTO","NU_SALAS_EXISTENTES","NU_EQUIP_TV","NU_EQUIP_COPIADORA",
                "NU_EQUIP_IMPRESSORA","NU_EQUIP_SOM","NU_EQUIP_MULTIMIDIA","NU_COMP_ADMINISTRATIVO",
                "NU_COMP_ALUNO","IN_INTERNET","NU_FUNCIONARIOS","IN_ALIMENTACAO"]
ItensInfra = TabelaInfra[3:]
pesos = [20,50,40,50,25,20,40,25,30,15,5,3,10,5,10,4,5,3,20,10,40]
sequencia = list(range(len(ItensInfra)-1))

def agrupamentoTurmas(x):
    result = {
        'QTD_ALUNOS_POR_ESCOLA': x['NU_MATRICULAS'].sum()
    }
    return pd.Series(result)

def agrupamentoMunicipio(x):
    result = {'NU_ANO_CENSO': x['NU_ANO_CENSO'].min(),
              'CO_ENTIDADE': x['CO_ENTIDADE'].min(),
              'MEDIA_QTD_ALUNOS_POR_ESCOLA': x['QTD_ALUNOS_POR_ESCOLA'].mean(),
              'MEDIA_NU_COMP_PARA_ALUNOS': x['NU_COMP_ALUNO'].mean(),
              'COMP_POR_ALUNO(%)': x['NUM_COMP_POR_ALUNO'].mean(),
              'NUM_ESCOLAS_INTERNET_MUNIC': x['IN_INTERNET'].sum(),
              'MEDIA_SALAS_EXISTENTES': x['NU_SALAS_EXISTENTES'].mean(),
              'MEDIA_PONTUACAO': x['PONTUACAO'].mean()
    }
    return pd.Series(result)

def gerarTabelaItensEscolas(ano): # Gera uma tabela para correlacionar com algum índice
    dfEscolas = pd.read_csv('../Dados/escolas'+ano+'.csv',low_memory=False, encoding='ISO-8859-1', sep='|')
    dfEscolas["PONTUACAO"] = sum( list(map(lambda x,y: x * dfEscolas[ItensInfra[y]], pesos, sequencia)) )
    dfEscolas = dfEscolas[['NU_ANO_CENSO', 'CO_ENTIDADE', 'CO_MUNICIPIO' ,'NU_COMP_ALUNO', 'IN_INTERNET', 'NU_SALAS_EXISTENTES', 'PONTUACAO']]
    dfEscolas.to_csv('itensPorEscolas'+ano+'_out.csv','|')
    return dfEscolas

def gerarTabelaQtdAlunosPorEscola(ano): # Gera uma tabela com a qtd de alunos por escola
    dfTurmas = pd.read_csv('../Dados/turmas'+ano+'.csv',low_memory=False, encoding='ISO-8859-1', sep='|')
    dfTurmasAgrupado = dfTurmas.groupby('CO_ENTIDADE')
    tabelaQtdAlunosPorEscola = dfTurmasAgrupado.apply(agrupamentoTurmas)
    tabelaQtdAlunosPorEscola.to_csv('qtdAlunosPorEscola'+ano+'_out.csv','|')
    return tabelaQtdAlunosPorEscola

def mergeTabelas(ano): # Faz o merge de ItensEscolas com QtdAlunosPorEscola
    itensEscolas = pd.read_csv('../Dados/Correlacao/itensPorEscolas'+ano+'_out.csv',low_memory=False, encoding='ISO-8859-1', sep='|')
    qtdAlunosEscola = pd.read_csv('../Dados/Correlacao/qtdAlunosPorEscola'+ano+'_out.csv',low_memory=False, encoding='ISO-8859-1', sep='|')
    mergeItens_QtdAlunos = pd.merge(itensEscolas, qtdAlunosEscola, how='inner', on='CO_ENTIDADE')
    mergeItens_QtdAlunos["NUM_COMP_POR_ALUNO"] = 100 * mergeItens_QtdAlunos['NU_COMP_ALUNO']/mergeItens_QtdAlunos['QTD_ALUNOS_POR_ESCOLA'] #% de Comp por Aluno
    mergeItens_QtdAlunos.to_csv('itens_Por_Escola'+ano+'_out.csv','|')
    tabelaItens_Municipio = agruparMunicipio(ano,mergeItens_QtdAlunos)
    return mergeItens_QtdAlunos, tabelaItens_Municipio

def agruparMunicipio(ano,tabela):  #Tabela para correlacionar com IOEB
    tabelaAgrupada = tabela.groupby('CO_MUNICIPIO')
    tabelaItens_Municipio = tabelaAgrupada.apply(agrupamentoMunicipio)
    tabelaItens_Municipio.to_csv('../Dados/Correlacao/itens_Por_Municipio'+ano+'_out.csv','|')
    return tabelaItens_Municipio

lista_anos = ['2015','2017']

listaTabelasQtdAlunosPorEscola = list(map(lambda x: gerarTabelaQtdAlunosPorEscola(x), lista_anos)) #Roda só um vez, gerando as tabelas

listaTabelasItensEscolas = list(map(lambda x: gerarTabelaItensEscolas(x), lista_anos)) #Roda só um vez, gerando as tabelas

listaItensPorEscola, listaItensPorMunicipio = list(map(lambda x: mergeTabelas(x), lista_anos)) #Roda só um vez, gerando as tabelas


#!/usr/bin/env python
"""
Converts between Probely's Navigation sequences and Selenium.

We can not guarantee that the conversion will be 100% compatible.
"""
import argparse
import json
import re
import uuid
import os
from time import time

items_not_supported = []

def getUUID():
    return str(uuid.uuid4())

def getSeleniumCssAndXPath(targets, target):
    css = None
    xpath = None
    for item in targets:
        if item[1] == 'css:finder':
            css = item[0].replace('css=', '')
        if item[1] == 'xpath:position':
            xpath = item[0].replace('xpath=', '')

    if css is None and target:
        if target.startswith('name='):
            css = '[{}]'.format(target)
        elif target.startswith('id='):
            css = '[{}]'.format(target)
    return (css, xpath)

def convertProbely2Selenium(data, inputFp, outputFp=None):
    name = os.path.basename(inputFp.name)
    obj = {
        'id': getUUID(),
        'version': '2.0',
        'name': name,
        'url': None,
        'tests': [{
            'id': getUUID(),
            'name': name,
            'commands': []
        }],
        'suites': [{
            'id': getUUID(),
            'name': 'Default Suite',
            'persistSession': False,
            'parallel': False,
            'timeout': 300,
            'tests': [getUUID()]
        }],
        'urls': [],
        'plugins': []
    }
    if len(data) == 0:
        raise Exception('No data in Probely recording file to be converted.')

    for idx, item in enumerate(data):
        if idx == 0:
            if item['type'] == 'goto':
                m = re.search('(https?://[^/]+)(/?.*)', item.get('url'))
                url_base = m.group(1)
                url_path = m.group(2)
                obj['url'] = url_base
                obj['urls'].append(url_base)
                obj['tests'][0]['commands'].append({
                    'id': getUUID(),
                    'comment': '',
                    'command': 'open',
                    'target': url_path,
                    'targets': [],
                    'value': ''
                })
                obj['tests'][0]['commands'].append({
                    'id': getUUID(),
                    'comment': '',
                    'command': 'setWindowSize',
                    'target': '{}x{}'.format(item.get('windowWidth', '1800'), item.get('windowHeight', '1200')),
                    'targets': [],
                    'value': ''
                })
            else:
                raise Exception('First item must be a "goto" with an URL')
        else:
            css = 'css={}'.format(item.get('css'))
            xpath = 'xpath={}'.format(item.get('xpath'))
            if item.get('type') == 'click' or item.get('type') == 'bclick':
                obj['tests'][0]['commands'].append({
                    'id': getUUID(),
                    'comment': '',
                    'command': 'click',
                    'target': css,
                    'targets': [
                        [css, 'css:finder'],
                        [xpath, 'xpath:position']
                    ],
                    'value': ''
                })
            elif item.get('type') == 'mouseover':
                obj['tests'][0]['commands'].append({
                    'id': getUUID(),
                    'comment': '',
                    'command': 'mouseOver',
                    'target': css,
                    'targets': [
                        [css, 'css:finder'],
                        [xpath, 'xpath:position']
                    ],
                    'value': ''
                })
            elif item.get('type') == 'fill_value':
                obj['tests'][0]['commands'].append({
                    'id': getUUID(),
                    'comment': '',
                    'command': 'type',
                    'target': css,
                    'targets': [
                        [css, 'css:finder'],
                        [xpath, 'xpath:position']
                    ],
                    'value': item.get('value', '')
                })
            elif item.get('type') == 'press_key' and item.get('value') == 13:
                obj['tests'][0]['commands'].append({
                    'id': getUUID(),
                    'comment': '',
                    'command': 'sendKeys',
                    'target': css,
                    'targets': [
                        [css, 'css:finder'],
                        [xpath, 'xpath:position']
                    ],
                    'value': '${KEY_ENTER}'
                })
            elif item.get('type') == 'change' and item.get('subtype') == 'select':
                obj['tests'][0]['commands'].append({
                    'id': getUUID(),
                    'comment': '',
                    'command': 'select',
                    'target': css,
                    'targets': [
                        [css, 'css:finder'],
                        [xpath, 'xpath:position']
                    ],
                    'value': 'value={}'.format(item.get('value', ''))
                })
            elif item.get('type') == 'change' and item.get('subtype') == 'check':
                obj['tests'][0]['commands'].append({
                    'id': getUUID(),
                    'comment': '',
                    'command': 'click',
                    'target': css,
                    'targets': [
                        [css, 'css:finder'],
                        [xpath, 'xpath:position']
                    ],
                    'value': ''
                })
            elif item.get('type') == 'dbclick':
                obj['tests'][0]['commands'].append({
                    'id': getUUID(),
                    'comment': '',
                    'command': 'doubleClick',
                    'target': css,
                    'targets': [
                        [css, 'css:finder'],
                        [xpath, 'xpath:position']
                    ],
                    'value': ''
                })
            else:
                items_not_supported.append('{} => {}'.format(idx, item.get('type')))

    return obj

def convertSelenium2Probely(data):
    obj = []
    timestamp = int(time()) * 1000
    tests_arr = data.get('tests')
    if tests_arr is None or len(tests_arr) == 0:
        raise Exception('No tests in Selenium file to be converted.')

    commands_arr = tests_arr[0].get('commands')
    if commands_arr is None or len(commands_arr) == 0:
        raise Exception('No commands in Selenium file to be converted.')

    url_base = data.get('url')
    # get first url
    first_command = commands_arr[0].get('command')
    second_command = commands_arr[1].get('command')
    url_path = commands_arr[0].get('target')
    dimensions = commands_arr[1].get('target')
    if first_command != 'open' or second_command != 'setWindowSize':
        raise Exception('Selenium first command must be "open" or second command must be "setWindowSize"')
    if url_path is None:
        raise Exception('Selenium first command must have a "target"')

    windowWidth = 1800
    windowHeight = 1200
    if dimensions:
        m = re.search('([0-9]+)x([0-9]+)', dimensions)
        windowWidth = int(m.group(1))
        windowHeight = int(m.group(2))

    obj.append({
        'type': 'goto',
        'urlType': 'force',
        'url': '{}{}'.format(url_base, url_path),
        'timestamp': timestamp,
        'windowWidth': windowWidth,
        'windowHeight': windowHeight
    })
    for idx, item in enumerate(commands_arr):
        if idx == 0 or idx == 1:
            continue
        else:
            css, xpath = getSeleniumCssAndXPath(item.get('targets'), item.get('target'))
            if css is None:
                continue
            if item.get('command') == 'click':
                timestamp += 1000
                obj.append({
                    'timestamp': timestamp,
                    'type': 'click',
                    'css': css,
                    'xpath': xpath,
                    'value': '',
                    'frame': None
                })
            elif item.get('command') == 'mouseOver':
                timestamp += 1000
                obj.append({
                    'timestamp': timestamp,
                    'type': 'mouseover',
                    'css': css,
                    'xpath': xpath,
                    'value': '',
                    'frame': None
                })
            elif item.get('command') == 'type':
                timestamp += 1000
                obj.append({
                    'timestamp': timestamp,
                    'type': 'fill_value',
                    'css': css,
                    'xpath': xpath,
                    'value': item.get('value', ''),
                    'frame': None
                })
            elif item.get('command') == 'sendKeys' and item.get('value') == '${KEY_ENTER}':
                timestamp += 1000
                obj.append({
                    'timestamp': timestamp,
                    'type': 'press_key',
                    'css': css,
                    'xpath': xpath,
                    'value': 13,
                    'frame': None
                })
            elif item.get('command') == 'select':
                timestamp += 1000
                select_value = item.get('value', '').replace('label=', '').replace('value=', '')
                obj.append({
                    'timestamp': timestamp,
                    'type': 'change',
                    'subtype': 'select',
                    'css': css,
                    'xpath': xpath,
                    'value': select_value,
                    'selected': 1,  # hardcoded, not correct
                    'frame': None
                })
            elif item.get('command') == 'doubleClick':
                timestamp += 1000
                obj.append({
                    'timestamp': timestamp,
                    'type': 'dblclick',
                    'css': css,
                    'xpath': xpath,
                    'value': '',
                    'frame': None
                })
            else:
                items_not_supported.append('{} => {}'.format(idx, item.get('command')))

    return obj

def run():
    parser = argparse.ArgumentParser(description='Converts Probely navigation sequences to selenium or selenium to Probely navigation sequences')
    parser.add_argument('-c', '--convert', help='<probely2selenium>/<selenium2probely>', choices=['probely2selenium', 'selenium2probely'])
    parser.add_argument('-i', '--input', help='Input file', type=argparse.FileType('r'))
    parser.add_argument('-o', '--output', help='Output file', type=argparse.FileType('w'))
    args = parser.parse_args()

    if args.convert == 'probely2selenium' and not args.output.name.endswith('.side'):
        raise Exception('Error: Selenium file name must use ".side" extension')

    input_data = json.load(args.input)

    if args.convert == 'probely2selenium':
        out_data = convertProbely2Selenium(input_data, args.input)
    elif args.convert == 'selenium2probely':
        out_data = convertSelenium2Probely(input_data)

    final_json = json.dumps(out_data, indent=2)
    args.output.write(final_json)

    if len(items_not_supported) > 0:
        print('Warning:')
        print('Items not supported/converted from positions: {}'.format(str(items_not_supported)))

    print('Done.')
    print('File converted to file: {}'.format(args.output.name))

if __name__ == '__main__':
    run()


# Copyright (c) 2009-2016 Simon van Heeringen <simon.vanheeringen@gmail.com>
#
# This module is free software. You can redistribute it and/or modify it under
# the terms of the MIT License, see the file COPYING included with this
# distribution.

"""
Module to compare DNA sequence motifs (positional frequency matrices)
"""
from __future__ import print_function

# Python imports
import sys
import os
import random
import logging

# External imports
from scipy.stats import norm,entropy,chi2_contingency
from scipy.spatial import distance
import numpy as np

# GimmeMotifs imports
from gimmemotifs.config import MotifConfig
from gimmemotifs.c_metrics import pwmscan,score
from gimmemotifs.motif import parse_motifs
# pool import is at the bottom

try:
    import copy_reg
    import types
    def _pickle_method(m):
        if m.im_self is None:
            return getattr, (m.im_class, m.im_func.func_name)
        else:
            return getattr, (m.im_self, m.im_func.func_name)

    copy_reg.pickle(types.MethodType, _pickle_method)
except:
    pass

# Create random sequence
nucs = []
L = 10 ** 4
for i in range(L):
    nucs.append(random.choice(['A', 'C', 'T', 'G']))
RANDOM_SEQ = "".join(nucs)

# Function that can be parallelized
def _get_all_scores(mc, motifs, dbmotifs, match, metric, combine, pval):

    try:
        scores = {}
        for m1 in motifs:
            scores[m1.id] = {}
            for m2 in dbmotifs:
                scores[m1.id][m2.id] = mc.compare_motifs(m1, m2, match, metric, combine, pval=pval)
        return scores
    except Exception:
        logging.exception("_get_all_scores failed")

def akl(x,y):
    """ Calcylates the average Kullback-Leibler similarity
    See Mahony,  2007
    """
    return 10 - (entropy(x,y) + entropy(y,x)) / 2.0

def chisq(x,y):
    return chi2_contingency([x, y])[1]

def ssd(x,y):
    """ Sum of squared distances
    """
    return np.sum([(a-b)**2 for a,b in zip(x,y)] )

def seqcor(m1, m2, seq=None):
    l1 = len(m1)
    l2 = len(m2)

    l = max(l1, l2)

    if seq is None:
        seq = RANDOM_SEQ

    # Scan random sequence
    result1 = pwmscan(seq, m1.pwm, m1.pwm_min_score(), len(seq), False, True)
    result2 = pwmscan(seq, m2.pwm, m2.pwm_min_score(), len(seq), False, True)
    result1 = np.array(result1)
    result2 = np.array(result2)

    # Return maximum correlation
    c = []
    for i in range(l1):
        c.append(1 - distance.correlation(result1[:L-l-i],result2[i:L-l]))
    for i in range(l2):
        c.append(1 - distance.correlation(result1[i:L-l],result2[:L-l-i]))
    return max(c)

class MotifComparer(object):
    def __init__(self):
        self.config = MotifConfig()
        self.metrics = ["pcc", "ed", "distance", "wic"]
        self.combine = ["mean", "sum"]
        self._load_scores()
        # Create a parallel python job server, to use for fast motif comparison

    def _load_scores(self):
        self.scoredist = {}
        for metric in self.metrics:
            self.scoredist[metric] = {"total": {}, "subtotal": {}}
            for match in ["total", "subtotal"]:
                for combine in ["mean"]:
                    self.scoredist[metric]["%s_%s" % (match, combine)] = {}
                    score_file = os.path.join(self.config.get_score_dir(), "%s_%s_%s_score_dist.txt" % (match, metric, combine))
                    if os.path.exists(score_file):
                        with open(score_file) as f:
                            for line in f:
                                l1, l2, m, sd = line.strip().split("\t")[:4]
                                self.scoredist[metric]["%s_%s" % (match, combine)].setdefault(int(l1), {})[int(l2)] = [float(m), float(sd)]

    def compare_motifs(self, m1, m2, match="total", metric="wic", combine="mean", pval=False):

        if metric == "seqcor":
            return seqcor(m1, m2)
        elif match == "partial":
            if pval:
                return self.pvalue(m1, m2, "total", metric, combine, self.max_partial(m1.pwm, m2.pwm, metric, combine))
            elif metric in ["pcc", "ed", "distance", "wic", "chisq"]:
                return self.max_partial(m1.pwm, m2.pwm, metric, combine)
            else:
                return self.max_partial(m1.pfm, m2.pfm, metric, combine)

        elif match == "total":
            if pval:
                return self.pvalue(m1, m2, match, metric, combine, self.max_total(m1.pwm, m2.pwm, metric, combine))
            elif metric == "pcc":
                sys.stderr.write("Can't calculate PCC of columns with equal distribution!\n")
                return None
            elif metric in ["ed", "distance", "wic", "chisq"]:
                return self.max_total(m1.pwm, m2.pwm, metric, combine)
            else:
                return self.max_total(m1.pfm, m2.pfm, metric, combine)

        elif match == "subtotal":
            if metric in ["pcc", "ed", "distance", "wic", "chisq"]:
                return self.max_subtotal(m1.pwm, m2.pwm, metric, combine)
            else:
                return self.max_subtotal(m1.pfm, m2.pfm, metric, combine)

    def _check_length(self, l):
        # Set the length to a length represented in randomly generated JASPAR motifs
        if l < 4:
            return 4
        if l == 13:
            return 14
        if l == 17:
            return 18
        if l == 19:
            return 20
        if l == 21:
            return 22
        if l > 22:
            return 30
        return l

    def pvalue(self, m1, m2, match, metric, combine, score):
        l1, l2 = len(m1.pwm), len(m2.pwm)

        l1 = self._check_length(l1)
        l2 = self._check_length(l2)

        m,s = self.scoredist[metric]["%s_%s" % (match, combine)][l1][l2]

        try:
            [1 - norm.cdf(score[0], m, s), score[1], score[2]]
        except Exception as e:
            print("Error with score: {}\n{}".format(score, e))
            return [1, np.nan, np.nan]
        return [1 - norm.cdf(score[0], m, s), score[1], score[2]]

    def score_matrices(self, matrix1, matrix2, metric, combine):
        if metric in self.metrics and combine in self.combine:
            s = score(matrix1, matrix2, metric, combine)

            if s != s:
                return None
            else:
                return s

        else:
            if metric == "akl":
                func = akl
            elif metric == "chisq":
                func = chisq
            elif metric == "ssd":
                func = ssd
            else:
                try:
                    func = getattr(distance, metric)
                except:
                    raise Exception("Unknown metric '{}'".format(metric))

            scores = []
            for pos1,pos2 in zip(matrix1,matrix2):
                scores.append(func(pos1, pos2))
            if combine == "mean":
                return np.mean(scores)
            elif combine == "sum":
                return np.sum(scores)
            else:
                raise ValueError("Unknown combine")

    def max_subtotal(self, matrix1, matrix2, metric, combine):
        scores = []
        min_overlap = 4

        if len(matrix1) < min_overlap or len(matrix2) < min_overlap:
            return self.max_total(matrix1, matrix2, metric, combine)

        #return c_max_subtotal(matrix1, matrix2, metric, combine)

        for i in range(-(len(matrix2) - min_overlap), len(matrix1) - min_overlap + 1):
            p1,p2 = self.make_equal_length_truncate(matrix1, matrix2, i)
            s = self.score_matrices(p1, p2, metric, combine)
            if s:
                scores.append([s, i, 1])

        rev_matrix2 = [row[::-1] for row in matrix2[::-1]]
        for i in range(-(len(matrix2) - min_overlap), len(matrix1) - min_overlap + 1):
            p1,p2 = self.make_equal_length_truncate(matrix1, rev_matrix2, i)
            s = self.score_matrices(p1, p2, metric, combine)
            if s:
                scores.append([s, i, -1])

        if not scores:
            return []
        return sorted(scores, key=lambda x: x[0])[-1]

    def max_partial(self, matrix1, matrix2, metric, combine):

        scores = []

        for i in range(-(len(matrix2) -1), len(matrix1)):
            p1,p2 = self.make_equal_length_truncate_second(matrix1, matrix2, i)
            s = self.score_matrices(p1, p2, metric, combine)
            if s:
                scores.append([s, i, 1])

        rev_matrix2 = [row[::-1] for row in matrix2[::-1]]
        for i in range(-(len(matrix2) -1), len(matrix1)):
            p1,p2 = self.make_equal_length_truncate_second(matrix1, rev_matrix2, i)
            s = self.score_matrices(p1, p2, metric, combine)
            if s:
                scores.append([s, i, -1])

        if not scores:
            return []
        return sorted(scores, key=lambda x: x[0])[-1]

    def max_total(self, matrix1, matrix2, metric, combine):
        scores = []

        for i in range(-(len(matrix2) -1), len(matrix1)):
            p1,p2 = self.make_equal_length(matrix1, matrix2, i)
            s = self.score_matrices(p1, p2, metric, combine)
            if s:
                scores.append([s, i, 1])

        rev_matrix2 = [row[::-1] for row in matrix2[::-1]]
        for i in range(-(len(matrix2) -1), len(matrix1)):
            p1,p2 = self.make_equal_length(matrix1, rev_matrix2, i)
            s = self.score_matrices(p1, p2, metric, combine)
            if s:
                scores.append([s, i, -1])

        if not scores:
            sys.stdout.write("No score {} {}".format(matrix1, matrix2))
            return []
        return sorted(scores, key=lambda x: x[0])[-1]

    def make_equal_length(self, pwm1, pwm2, pos, bg=None):
        if bg is None:
            bg = [0.25,0.25,0.25,0.25]

        p1 = pwm1[:]
        p2 = pwm2[:]

        if pos < 1:
            p1 = [bg for _ in range(-pos)] + p1
        else:
            p2 = [bg for _ in range(pos)] + p2

        diff = len(p1) - len(p2)
        if diff > 0:
            p2 += [bg for _ in range(diff)]
        elif diff < 0:
            p1 += [bg for _ in range(-diff)]

        return p1,p2

    def make_equal_length_truncate(self, pwm1, pwm2, pos):
        p1 = pwm1[:]
        p2 = pwm2[:]

        if pos < 0:
            p2 = p2[-pos:]
        elif pos > 0:
            p1 = p1[pos:]

        if len(p1) > len(p2):
            p1 = p1[:len(p2)]
        else:
            p2 = p2[:len(p1)]
        return p1, p2

    def make_equal_length_truncate_second(self, pwm1, pwm2, pos, bg=None):
        if bg is None:
            bg = [0.25,0.25,0.25,0.25]

        p1 = pwm1[:]
        p2 = pwm2[:]

        if pos < 0:
            p2 = p2[-pos:]
        else:
            p2 = [bg for _ in range(pos)] + p2

        diff = len(p1) - len(p2)
        if diff > 0:
            p2 += [bg for _ in range(diff)]
        elif diff < 0:
            p2 = p2[:len(p1)]
        return p1,p2

    def get_all_scores(self, motifs, dbmotifs, match, metric, combine, pval=False, parallel=True, trim=None, ncpus=None):

        # trim motifs first, if specified
        if trim:
            for m in motifs:
                m.trim(trim)
            for m in dbmotifs:
                m.trim(trim)

        # hash of result scores
        scores ={}

        if parallel:
            # Divide the job into big chunks, to keep parallel overhead to minimum
            # Number of chunks = number of processors available
            if ncpus is None:
                ncpus = int(MotifConfig().get_default_params()["ncpus"])

            pool = Pool(processes=ncpus, maxtasksperchild=1000)

            batch_len = len(dbmotifs) // ncpus
            if batch_len <= 0:
                batch_len = 1
            jobs = []
            for i in range(0, len(dbmotifs), batch_len):
                # submit jobs to the job server

                p = pool.apply_async(_get_all_scores,
                    args=(self, motifs, dbmotifs[i: i + batch_len], match, metric, combine, pval))
                jobs.append(p)

            pool.close()
            for job in jobs:
                # Get the job result
                result = job.get()
                # and update the result score
                for m1,v in result.items():
                    for m2, s in v.items():
                        if m1 not in scores:
                            scores[m1] = {}
                        scores[m1][m2] = s

            pool.join()
        else:
            # Do the whole thing at once if we don't want parallel
            scores = _get_all_scores(self, motifs, dbmotifs, match, metric, combine, pval)

        return scores

    def get_closest_match(self, motifs, dbmotifs=None, match="partial", metric="wic",combine="mean", parallel=True, ncpus=None):
        """Return best match in database for motifs.

        Parameters
        ----------

        motifs : list or str
            Filename of motifs or list of motifs.

        dbmotifs ; list or str, optional
            Database motifs, default will be used if not specified.

        match : str, optional

        metric : str, optional

        combine : str, optional

        ncpus : int, optional
            Number of threads to use.

        Returns
        -------

        closest_match : dict
        """

        if dbmotifs is None:
            pwm = self.config.get_default_params()["motif_db"]
            pwmdir = self.config.get_motif_dir()
            dbmotifs = os.path.join(pwmdir, pwm)

        motifs = parse_motifs(motifs)
        dbmotifs = parse_motifs(dbmotifs)

        dbmotif_lookup = dict([(m.id, m) for m in dbmotifs])

        scores = self.get_all_scores(motifs, dbmotifs, match, metric, combine, parallel=parallel, ncpus=ncpus)
        for motif in scores:
            scores[motif] = sorted(
                    scores[motif].items(),
                    key=lambda x:x[1][0]
                    )[-1]

        for motif in motifs:
            dbmotif, score = scores[motif.id]
            pval, pos, orient = self.compare_motifs(
                    motif, dbmotif_lookup[dbmotif], match, metric, combine, True)

            scores[motif.id] = [dbmotif, (list(score) + [pval])]

        return scores

    def generate_score_dist(self, motifs, match, metric, combine):

        score_file = os.path.join(self.config.get_score_dir(), "%s_%s_%s_score_dist.txt" % (match, metric, combine))
        f = open(score_file, "w")

        all_scores = {}
        for l in [len(motif) for motif in motifs]:
            all_scores[l] = {}

        sorted_motifs = {}
        for l in all_scores.keys():
            sorted_motifs[l] = [motif for motif in motifs if len(motif) == l]

        for l1 in all_scores.keys():
            for l2 in all_scores.keys():
                scores = self.get_all_scores(sorted_motifs[l1], sorted_motifs[l2], match, metric, combine)
                scores = [[y[0] for y in x.values() if y] for x in scores.values()]
                scores = np.array(scores).ravel()
                f.write("%s\t%s\t%s\t%s\n" % (l1, l2, np.mean(scores), np.std(scores)))

        f.close()

# import here is necessary as workaround
# see: http://stackoverflow.com/questions/18947876/using-python-multiprocessing-pool-in-the-terminal-and-in-code-modules-for-django
try:
    from multiprocessing import Pool
except:
    pass


from django import forms
from django.forms.util import to_current_timezone
from django.conf import settings
from django.utils import translation
from django.utils.safestring import mark_safe

default_date_format = getattr(settings, 'DATE_INPUT_FORMATS', None)
if default_date_format:
    default_date_format = str(default_date_format[0])

default_time_format = getattr(settings, 'TIME_INPUT_FORMATS', None)
if default_time_format:
    default_time_format = str(default_time_format[0])

def javascript_date_format(python_date_format):
    format = python_date_format.replace(r'%Y', 'yyyy')
    format = format.replace(r'%m', 'mm')
    format = format.replace(r'%d', 'dd')
    if '%' in format:
        format = ''
    if not format:
        format = 'yyyy-mm-dd'
    return format

def javascript_time_format(python_time_format):
    format = python_time_format.replace(r'%H', 'HH')
    format = format.replace(r'%M', 'MM')
    format = format.replace(r'%S', 'SS')
    if '%' in format:
        format = ''
    if not format:
        format = 'HH:MM:SS'
    return format

def add_to_css_class(classes, new_class):
    new_class = new_class.strip()
    if new_class:
        # Turn string into list of classes
        classes = classes.split(" ")
        # Strip whitespace
        classes = [c.strip() for c in classes]
        # Remove empty elements
        classes = filter(None, classes)
        # Test for existing
        if not new_class in classes:
            classes.append(new_class)
            # Convert to string
        classes = u" ".join(classes)
    return classes

def create_prepend_append(**kwargs):
    bootstrap = {}
    bootstrap['append'] = kwargs.pop('append', None)
    bootstrap['prepend'] = kwargs.pop('prepend', None)
    return bootstrap, kwargs

class BootstrapUneditableInput(forms.TextInput):

    def render(self, name, value, attrs=None):
        if attrs is None:
            attrs = {}
        attrs['type'] = 'hidden'
        klass = add_to_css_class(self.attrs.pop('class', ''), 'uneditable-input')
        klass = add_to_css_class(klass, attrs.pop('class', ''))
        base = super(BootstrapUneditableInput, self).render(name, value, attrs)
        return mark_safe(base + u'%s' % (klass, value))

class BootstrapTextInput(forms.TextInput):

    def __init__(self, *args, **kwargs):
        self.bootstrap, kwargs = create_prepend_append(**kwargs)
        super(BootstrapTextInput, self).__init__(*args, **kwargs)

class BootstrapPasswordInput(forms.PasswordInput):

    def __init__(self, *args, **kwargs):
        self.bootstrap, kwargs = create_prepend_append(**kwargs)
        super(BootstrapPasswordInput, self).__init__(*args, **kwargs)

class BootstrapDateInput(forms.DateInput):

    bootstrap = {
        'append': mark_safe(''),
        'prepend': None,
    }

    class Media:
        js = (
            settings.STATIC_URL + 'datepicker/js/bootstrap-datepicker.js',
        )
        lang = translation.get_language().split('-')[0].lower()
        if lang != 'en':
            js = js + (
                settings.STATIC_URL + 'datepicker/js/locales/bootstrap-datepicker.%s.js' % lang,
            )
        js = js + (
            settings.STATIC_URL + 'bootstrap_toolkit/js/init_datepicker.js',
        )
        css = {
            'screen': (
                settings.STATIC_URL + 'datepicker/css/datepicker.css',
            )
        }

    def render(self, name, value, attrs=None):
        if attrs is None:
            attrs = {}
        format = self.format
        if not format:
            format = default_date_format
        attrs['data-date-format'] = javascript_date_format(format)
        attrs['data-date-language'] = translation.get_language().split('-')[0].lower()
        attrs['data-bootstrap-widget'] = 'datepicker'
        return super(BootstrapDateInput, self).render(name, value, attrs)

class BootstrapTimeInput(forms.TimeInput):

    bootstrap = {
        'append': mark_safe(''),
        'prepend': None,
    }

    class Media:
        js = (
            settings.STATIC_URL + 'timepicker/js/bootstrap-timepicker.js',
        )
        lang = translation.get_language().split('-')[0].lower()
        if lang != 'en':
            js = js + (
                settings.STATIC_URL + 'timepicker/js/locales/bootstrap-timepicker.%s.js' % lang,
            )
        js = js + (
            settings.STATIC_URL + 'bootstrap_toolkit/js/init_timepicker.js',
        )
        css = {
            'screen': (
                settings.STATIC_URL + 'timepicker/css/timepicker.css',
            )
        }

    def render(self, name, value, attrs=None):
        if attrs is None:
            attrs = {}
        format = self.format
        if not format:
            format = default_time_format
        attrs['data-time-format'] = javascript_time_format(format)
        attrs['data-time-language'] = translation.get_language().split('-')[0].lower()
        attrs['data-bootstrap-widget'] = 'timepicker'
        return super(BootstrapTimeInput, self).render(name, value, attrs)

class BootstrapDateTimeInput(forms.MultiWidget):

    def __init__(self, attrs=None):
        widgets = (BootstrapDateInput(attrs=attrs),
                   BootstrapTimeInput(attrs=attrs))
        super(BootstrapDateTimeInput, self).__init__(widgets, attrs)

    def decompress(self, value):
        if value:
            value = to_current_timezone(value)
            return [value.date(), value.time().replace(microsecond=0)]
        return [None, None]


# -*- coding: utf-8 -*-

import hrmcompiler.parser as p
import hrmcompiler.assembler as a
import hrmcompiler.jsonassembler as ja
import hrmcompiler.semantic_check as checker
import hrmcompiler.conversion as conversion
import json

def calculate_optimized_ast(fhandle, args):
    result_ast = p.parse_it(fhandle)

    checker.perform_label_checks(result_ast)
    checker.perform_variable_checks(result_ast)

    result_ast = conversion.convert_ifnz_to_ifez(result_ast)
    result_ast = conversion.convert_iftojump(result_ast)
    if not args.no_jump_compression:
        result_ast = conversion.compress_jumps(result_ast)
    if not args.no_unreachable:
        result_ast = conversion.remove_unreachable_code(result_ast)
    if not args.no_jmp_then_label:
        unchanged = False
        while not unchanged:
            new_ast = conversion.fix_jmp_then_label(result_ast)
            unchanged = new_ast == result_ast
            result_ast = new_ast

    return result_ast

def main(args):
    with open(args.fname) as src:
        result_ast = calculate_optimized_ast(src, args)

        assembler = a.Assembler()
        assembler.convert(result_ast)

        with open(args.fname.replace(".hrm", ".json"), "w") as dst:
            json_assembler = ja.Assembler()
            json_assembler.convert(result_ast)
            json.dump(json_assembler.code, dst)

        print(" ------------------------ ")
        print("\n".join(assembler.code))