# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

# pylint: disable=too-many-statements
# pylint: disable=line-too-long
from enum import Enum
from argcomplete.completers import FilesCompleter

from azure.cli.core.commands.parameters import (
    get_resource_name_completion_list, name_type, get_enum_type, get_three_state_flag, tags_type)
from azure.cli.core.util import shell_safe_json_parse

from azure.cli.command_modules.cosmosdb._validators import (
    validate_failover_policies, validate_capabilities,
    validate_virtual_network_rules, validate_ip_range_filter,
    validate_role_definition_body,
    validate_role_definition_id,
    validate_fully_qualified_role_definition_id,
    validate_role_assignment_id,
    validate_scope)

from azure.cli.command_modules.cosmosdb.actions import (
    CreateLocation)
from azure.cli.command_modules.cosmosdb.custom import (
    CosmosKeyTypes)

SQL_GREMLIN_INDEXING_POLICY_EXAMPLE = """--idx "{\\"indexingMode\\": \\"consistent\\", \\"automatic\\": true, \\"includedPaths\\": [{\\"path\\": \\"/*\\"}], \\"excludedPaths\\": [{ \\"path\\": \\"/headquarters/employees/?\\"}, { \\"path\\": \\"/\\\\"_etag\\\\"/?\\"}]}"
"""

SQL_UNIQUE_KEY_POLICY_EXAMPLE = """--unique-key-policy "{\\"uniqueKeys\\": [{\\"paths\\": [\\"/path/to/key1\\"]}, {\\"paths\\": [\\"/path/to/key2\\"]}]}"
"""

SQL_GREMLIN_CONFLICT_RESOLUTION_POLICY_EXAMPLE = """--conflict-resolution-policy "{\\"mode\\": \\"lastWriterWins\\", \\"conflictResolutionPath\\": \\"/path\\"}"
"""

MONGODB_INDEXES_EXAMPLE = """--idx "[{\\"key\\": {\\"keys\\": [\\"_ts\\"]},\\"options\\": {\\"expireAfterSeconds\\": 1000}}, {\\"key\\": {\\"keys\\": [\\"user_id\\", \\"user_address\\"]}, \\"options\\": {\\"unique\\": \\"true\\"}}]"
"""

CASSANDRA_SCHEMA_EXAMPLE = """--schema "{\\"columns\\": [{\\"name\\": \\"columnA\\",\\"type\\": \\"uuid\\"}, {\\"name\\": \\"columnB\\",\\"type\\": \\"Ascii\\"}],\\"partitionKeys\\": [{\\"name\\": \\"columnA\\"}]}"
"""

SQL_ROLE_DEFINITION_EXAMPLE = """--body "{ \\"Id\\": \\"be79875a-2cc4-40d5-8958-566017875b39\\", \\"RoleName\\": \\"My Read Write Role\\", \\"Type\\": \\"CustomRole\\", \\"AssignableScopes\\": [ \\"/\\" ], \\"DataActions\\": [ \\"Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/create\\", \\"Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/read\\" ]}"
"""

class ThroughputTypes(str, Enum):
    autoscale = "autoscale"
    manual = "manual"

def load_arguments(self, _):
    from knack.arguments import CLIArgumentType
    from azure.mgmt.cosmosdb.models import KeyKind, DefaultConsistencyLevel, DatabaseAccountKind, TriggerType, TriggerOperation, ServerVersion, NetworkAclBypass

    with self.argument_context('cosmosdb') as c:
        c.argument('account_name', arg_type=name_type, help='Name of the Cosmos DB database account', completer=get_resource_name_completion_list('Microsoft.DocumentDb/databaseAccounts'), id_part='name')
        c.argument('database_id', options_list=['--db-name', '-d'], help='Database Name')

    with self.argument_context('cosmosdb create') as c:
        c.argument('account_name', completer=None)
        c.argument('key_uri', help="The URI of the key vault", is_preview=True)
        c.argument('enable_free_tier', arg_type=get_three_state_flag(), help="If enabled the account is free-tier.", is_preview=True)
        c.argument('assign_identity', nargs='*', help="accept system or user assigned identities separated by spaces. Use '[system]' to refer system assigned identity. Currently only system assigned identity is supported.", is_preview=True)

    for scope in ['cosmosdb create', 'cosmosdb update']:
        with self.argument_context(scope) as c:
            c.ignore('resource_group_location')
            c.argument('locations', nargs='+', action=CreateLocation)
            c.argument('tags', arg_type=tags_type)
            c.argument('default_consistency_level', arg_type=get_enum_type(DefaultConsistencyLevel), help="default consistency level of the Cosmos DB database account")
            c.argument('max_staleness_prefix', type=int, help="when used with Bounded Staleness consistency, this value represents the number of stale requests tolerated. Accepted range for this value is 1 - 2,147,483,647")
            c.argument('max_interval', type=int, help="when used with Bounded Staleness consistency, this value represents the time amount of staleness (in seconds) tolerated. Accepted range for this value is 1 - 100")
            c.argument('ip_range_filter', nargs='+', options_list=['--ip-range-filter'], validator=validate_ip_range_filter, help="firewall support. Specifies the set of IP addresses or IP address ranges in CIDR form to be included as the allowed list of client IPs for a given database account. IP addresses/ranges must be comma-separated and must not contain any spaces")
            c.argument('kind', arg_type=get_enum_type(DatabaseAccountKind), help='The type of Cosmos DB database account to create')
            c.argument('enable_automatic_failover', arg_type=get_three_state_flag(), help='Enables automatic failover of the write region in the rare event that the region is unavailable due to an outage. Automatic failover will result in a new write region for the account and is chosen based on the failover priorities configured for the account.')
            c.argument('capabilities', nargs='+', validator=validate_capabilities, help='set custom capabilities on the Cosmos DB database account.')
            c.argument('enable_virtual_network', arg_type=get_three_state_flag(), help='Enables virtual network on the Cosmos DB database account')
            c.argument('virtual_network_rules', nargs='+', validator=validate_virtual_network_rules, help='ACL\'s for virtual network')
            c.argument('enable_multiple_write_locations', arg_type=get_three_state_flag(), help="Enable Multiple Write Locations")
            c.argument('disable_key_based_metadata_write_access', arg_type=get_three_state_flag(), help="Disable write operations on metadata resources (databases, containers, throughput) via account keys")
            c.argument('enable_public_network', options_list=['--enable-public-network', '-e'], arg_type=get_three_state_flag(), help="Enable or disable public network access to server.")
            c.argument('enable_analytical_storage', arg_type=get_three_state_flag(), help="Flag to enable log storage on the account.", is_preview=True)
            c.argument('network_acl_bypass', arg_type=get_enum_type(NetworkAclBypass), options_list=['--network-acl-bypass'], help="Flag to enable or disable Network Acl Bypass.")
            c.argument('network_acl_bypass_resource_ids', nargs='+', options_list=['--network-acl-bypass-resource-ids', '-i'], help="List of Resource Ids to allow Network Acl Bypass.")
            c.argument('backup_interval', type=int, help="the frequency(in minutes) with which backups are taken (only for accounts with periodic mode backups)", arg_group='Backup Policy')
            c.argument('backup_retention', type=int, help="the time(in hours) for which each backup is retained (only for accounts with periodic mode backups)", arg_group='Backup Policy')
            c.argument('server_version', arg_type=get_enum_type(ServerVersion), help="Valid only for MongoDB accounts.", is_preview=True)
            c.argument('default_identity', help="The primary identity to access key vault in CMK related features. e.g. 'FirstPartyIdentity', 'SystemAssignedIdentity' and more.", is_preview=True)

    for scope in ['cosmosdb regenerate-key', 'cosmosdb keys regenerate']:
        with self.argument_context(scope) as c:
            c.argument('key_kind', arg_type=get_enum_type(KeyKind), help="The access key to regenerate.")

    with self.argument_context('cosmosdb failover-priority-change') as c:
        c.argument('failover_parameters', options_list=['--failover-policies'], validator=validate_failover_policies,
                   help="space-separated failover policies in 'regionName=failoverPriority' format. E.g eastus=0 westus=1", nargs='+')

    with self.argument_context('cosmosdb network-rule list') as c:
        c.argument('account_name', id_part=None)

    with self.argument_context('cosmosdb keys list') as c:
        c.argument('account_name', help="Cosmosdb account name", id_part=None)
        c.argument('key_type', arg_type=get_enum_type(CosmosKeyTypes), options_list=['--type'], help="The type of account key.")

    with self.argument_context('cosmosdb network-rule add') as c:
        c.argument('subnet', help="Name or ID of the subnet")
        c.argument('virtual_network', options_list=['--vnet-name', '--virtual-network'], help="The name of the VNET, which must be provided in conjunction with the name of the subnet")
        c.argument("ignore_missing_vnet_service_endpoint", options_list=['--ignore-missing-endpoint', '--ignore-missing-vnet-service-endpoint'], arg_type=get_three_state_flag(), help="Create firewall rule before the virtual network has vnet service endpoint enabled.")

    with self.argument_context('cosmosdb network-rule remove') as c:
        c.argument('subnet', help="Name or ID of the subnet")
        c.argument('virtual_network', options_list=['--vnet-name', '--virtual-network'], help="The name of the VNET, which must be provided in conjunction with the name of the subnet")

    with self.argument_context('cosmosdb collection') as c:
        c.argument('collection_id', options_list=['--collection-name', '-c'], help='Collection Name')
        c.argument('throughput', type=int, help='Offer Throughput (RU/s)')
        c.argument('partition_key_path', help='Partition Key Path, e.g., \'/properties/name\'')
        c.argument('indexing_policy', type=shell_safe_json_parse, completer=FilesCompleter(), help='Indexing Policy, you can enter it as a string or as a file, e.g., --indexing-policy @policy-file.json)')
        c.argument('default_ttl', type=int, help='Default TTL. Provide 0 to disable.')

    with self.argument_context('cosmosdb database') as c:
        c.argument('throughput', type=int, help='Offer Throughput (RU/s)')

    account_name_type = CLIArgumentType(options_list=['--account-name', '-a'], help="Cosmosdb account name.")
    database_name_type = CLIArgumentType(options_list=['--database-name', '-d'], help='Database name.')
    container_name_type = CLIArgumentType(options_list=['--container-name', '-c'], help='Container name.')
    max_throughput_type = CLIArgumentType(options_list=['--max-throughput'], help='The maximum throughput resource can scale to (RU/s). Provided when the resource is autoscale enabled. The minimum value can be 4000 (RU/s)')
    throughput_type = CLIArgumentType(options_list=['--throughput-type', '-t'], arg_type=get_enum_type(ThroughputTypes), help='The type of throughput to migrate to.')

    with self.argument_context('cosmosdb private-endpoint-connection') as c:
        c.argument('private_endpoint_connection_name', options_list=['--name', '-n'], required=False,
                   help='The name of the private endpoint connection associated with Azure Cosmos DB. '
                        'Required if --connection-id is not specified')
        c.argument('account_name', account_name_type, required=False,
                   help='Name of the Cosmos DB database account. Required if --connection-id is not specified')
        c.argument('resource_group_name', required=False,
                   help='The resource group name of specified Cosmos DB account. Required if --connection-id is not specified')

    for item in ['approve', 'reject', 'delete', 'show']:
        with self.argument_context('cosmosdb private-endpoint-connection {}'.format(item)) as c:
            c.extra('connection_id', options_list=['--id'], required=False,
                    help='The ID of the private endpoint connection associated with Azure Cosmos DB. '
                         'If specified --account-name --resource-group/-g and --name/-n, this should be omitted.')
            c.argument('description', options_list=['--description'], required=False, help='Comments for the {} operation.'.format(item))

    with self.argument_context('cosmosdb private-link-resource') as c:
        c.argument('account_name', account_name_type, required=True, help="Cosmosdb account name", id_part=None)

# SQL database
    with self.argument_context('cosmosdb sql database') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('database_name', options_list=['--name', '-n'], help="Database name")
        c.argument('throughput', help='The throughput of SQL database (RU/s). Default value is 400')
        c.argument('max_throughput', max_throughput_type)

# SQL container
    with self.argument_context('cosmosdb sql container') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('database_name', database_name_type)
        c.argument('container_name', options_list=['--name', '-n'], help="Container name")
        c.argument('partition_key_path', options_list=['--partition-key-path', '-p'], help='Partition Key Path, e.g., \'/address/zipcode\'')
        c.argument('partition_key_version', type=int, options_list=['--partition-key-version'], help='The version of partition key.')
        c.argument('default_ttl', options_list=['--ttl'], type=int, help='Default TTL. If the value is missing or set to "-1", items don’t expire. If the value is set to "n", items will expire "n" seconds after last modified time.')
        c.argument('indexing_policy', options_list=['--idx'], type=shell_safe_json_parse, completer=FilesCompleter(), help='Indexing Policy, you can enter it as a string or as a file, e.g., --idx @policy-file.json or ' + SQL_GREMLIN_INDEXING_POLICY_EXAMPLE)
        c.argument('unique_key_policy', options_list=['--unique-key-policy', '-u'], type=shell_safe_json_parse, completer=FilesCompleter(), help='Unique Key Policy, you can enter it as a string or as a file, e.g., --unique-key-policy @policy-file.json or ' + SQL_UNIQUE_KEY_POLICY_EXAMPLE)
        c.argument('conflict_resolution_policy', options_list=['--conflict-resolution-policy', '-c'], type=shell_safe_json_parse, completer=FilesCompleter(), help='Conflict Resolution Policy, you can enter it as a string or as a file, e.g., --conflict-resolution-policy @policy-file.json or ' + SQL_GREMLIN_CONFLICT_RESOLUTION_POLICY_EXAMPLE)
        c.argument('max_throughput', max_throughput_type)
        c.argument('throughput', help='The throughput of SQL container (RU/s). Default value is 400. Omit this parameter if the database has shared throughput unless the container should have dedicated throughput.')
        c.argument('analytical_storage_ttl', options_list=['--analytical-storage-ttl', '-t'], type=int, help='Analytical TTL, when analytical storage is enabled.')

# SQL stored procedure
    with self.argument_context('cosmosdb sql stored-procedure') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('database_name', database_name_type)
        c.argument('container_name', container_name_type)
        c.argument('stored_procedure_name', options_list=['--name', '-n'], help="StoredProcedure name")
        c.argument('stored_procedure_body', options_list=['--body', '-b'], completer=FilesCompleter(), help="StoredProcedure body, you can enter it as a string or as a file, e.g., --body @sprocbody-file.json")

# SQL trigger
    with self.argument_context('cosmosdb sql trigger') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('database_name', database_name_type)
        c.argument('container_name', container_name_type)
        c.argument('trigger_name', options_list=['--name', '-n'], help="Trigger name")
        c.argument('trigger_body', options_list=['--body', '-b'], completer=FilesCompleter(), help="Trigger body, you can enter it as a string or as a file, e.g., --body @triggerbody-file.json")
        c.argument('trigger_type', options_list=['--type', '-t'], arg_type=get_enum_type(TriggerType), help="Trigger type")
        c.argument('trigger_operation', options_list=['--operation'], arg_type=get_enum_type(TriggerOperation), help="The operation of the trigger.")

# SQL user defined function
    with self.argument_context('cosmosdb sql user-defined-function') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('database_name', database_name_type)
        c.argument('container_name', container_name_type)
        c.argument('user_defined_function_name', options_list=['--name', '-n'], help="UserDefinedFunction name")
        c.argument('user_defined_function_body', options_list=['--body', '-b'], completer=FilesCompleter(), help="UserDefinedFunction body, you can enter it as a string or as a file, e.g., --body @udfbody-file.json")

# MongoDB
    with self.argument_context('cosmosdb mongodb database') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('database_name', options_list=['--name', '-n'], help="Database name")
        c.argument('throughput', help='The throughput of MongoDB database (RU/s). Default value is 400')
        c.argument('max_throughput', max_throughput_type)

    with self.argument_context('cosmosdb mongodb collection') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('database_name', database_name_type)
        c.argument('collection_name', options_list=['--name', '-n'], help="Collection name")
        c.argument('shard_key_path', options_list=['--shard'], help="Sharding key path.")
        c.argument('indexes', options_list=['--idx'], type=shell_safe_json_parse, completer=FilesCompleter(), help='Indexes, you can enter it as a string or as a file, e.g., --idx @indexes-file.json or ' + MONGODB_INDEXES_EXAMPLE)
        c.argument('max_throughput', max_throughput_type)
        c.argument('analytical_storage_ttl', type=int, help='Analytical TTL, when analytical storage is enabled.')
        c.argument('throughput', help='The throughput of MongoDB collection (RU/s). Default value is 400. Omit this parameter if the database has shared throughput unless the collection should have dedicated throughput.')

# Cassandra
    with self.argument_context('cosmosdb cassandra keyspace') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('keyspace_name', options_list=['--name', '-n'], help="Keyspace name")
        c.argument('throughput', help='The throughput of Cassandra keyspace (RU/s). Default value is 400')
        c.argument('max_throughput', max_throughput_type)

    with self.argument_context('cosmosdb cassandra table') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('keyspace_name', options_list=['--keyspace-name', '-k'], help="Keyspace name")
        c.argument('table_name', options_list=['--name', '-n'], help="Table name")
        c.argument('default_ttl', options_list=['--ttl'], type=int, help='Default TTL. If the value is missing or set to "-1", items don’t expire. If the value is set to "n", items will expire "n" seconds after last modified time.')
        c.argument('schema', type=shell_safe_json_parse, completer=FilesCompleter(), help='Schema, you can enter it as a string or as a file, e.g., --schema @schema-file.json or ' + CASSANDRA_SCHEMA_EXAMPLE)
        c.argument('max_throughput', max_throughput_type)
        c.argument('analytical_storage_ttl', type=int, help='Analytical TTL, when analytical storage is enabled.')
        c.argument('throughput', help='The throughput of Cassandra table (RU/s). Default value is 400. Omit this parameter if the keyspace has shared throughput unless the table should have dedicated throughput.')

# Gremlin
    with self.argument_context('cosmosdb gremlin database') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('database_name', options_list=['--name', '-n'], help="Database name")
        c.argument('throughput', help='The throughput Gremlin database (RU/s). Default value is 400')
        c.argument('max_throughput', max_throughput_type)

    with self.argument_context('cosmosdb gremlin graph') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('database_name', database_name_type)
        c.argument('graph_name', options_list=['--name', '-n'], help="Graph name")
        c.argument('partition_key_path', options_list=['--partition-key-path', '-p'], help='Partition Key Path, e.g., \'/address/zipcode\'')
        c.argument('default_ttl', options_list=['--ttl'], type=int, help='Default TTL. If the value is missing or set to "-1", items don’t expire. If the value is set to "n", items will expire "n" seconds after last modified time.')
        c.argument('indexing_policy', options_list=['--idx'], type=shell_safe_json_parse, completer=FilesCompleter(), help='Indexing Policy, you can enter it as a string or as a file, e.g., --idx @policy-file.json or ' + SQL_GREMLIN_INDEXING_POLICY_EXAMPLE)
        c.argument('conflict_resolution_policy', options_list=['--conflict-resolution-policy', '-c'], type=shell_safe_json_parse, completer=FilesCompleter(), help='Conflict Resolution Policy, you can enter it as a string or as a file, e.g., --conflict-resolution-policy @policy-file.json or ' + SQL_GREMLIN_CONFLICT_RESOLUTION_POLICY_EXAMPLE)
        c.argument('max_throughput', max_throughput_type)
        c.argument('throughput', help='The throughput of Gremlin graph (RU/s). Default value is 400. Omit this parameter if the database has shared throughput unless the graph should have dedicated throughput.')

# Table
    with self.argument_context('cosmosdb table') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('table_name', options_list=['--name', '-n'], help="Table name")
        c.argument('throughput', help='The throughput of Table (RU/s). Default value is 400')
        c.argument('max_throughput', max_throughput_type)

# Throughput
    with self.argument_context('cosmosdb sql database throughput') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('database_name', options_list=['--name', '-n'], help="Database name")
        c.argument('throughput', type=int, help='The throughput of SQL database (RU/s).')
        c.argument('max_throughput', max_throughput_type)

    with self.argument_context('cosmosdb sql container throughput') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('database_name', database_name_type)
        c.argument('container_name', options_list=['--name', '-n'], help="Container name")
        c.argument('throughput', type=int, help='The throughput of SQL container (RU/s).')
        c.argument('max_throughput', max_throughput_type)

    with self.argument_context('cosmosdb mongodb database throughput') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('database_name', options_list=['--name', '-n'], help="Database name")
        c.argument('throughput', type=int, help='The throughput of MongoDB database (RU/s).')
        c.argument('max_throughput', max_throughput_type)

    with self.argument_context('cosmosdb mongodb collection throughput') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('database_name', database_name_type)
        c.argument('collection_name', options_list=['--name', '-n'], help="Collection name")
        c.argument('throughput', type=int, help='The throughput of MongoDB collection (RU/s).')
        c.argument('max_throughput', max_throughput_type)

    with self.argument_context('cosmosdb cassandra keyspace throughput') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('keyspace_name', options_list=['--name', '-n'], help="Keyspace name")
        c.argument('throughput', type=int, help='The throughput of Cassandra keyspace (RU/s).')
        c.argument('max_throughput', max_throughput_type)

    with self.argument_context('cosmosdb cassandra table throughput') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('keyspace_name', options_list=['--keyspace-name', '-k'], help="Keyspace name")
        c.argument('table_name', options_list=['--name', '-n'], help="Table name")
        c.argument('throughput', type=int, help='The throughput of Cassandra table (RU/s).')
        c.argument('max_throughput', max_throughput_type)

    with self.argument_context('cosmosdb gremlin database throughput') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('database_name', options_list=['--name', '-n'], help="Database name")
        c.argument('throughput', type=int, help='The throughput of Gremlin database (RU/s).')
        c.argument('max_throughput', max_throughput_type)

    with self.argument_context('cosmosdb gremlin graph throughput') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('database_name', database_name_type)
        c.argument('graph_name', options_list=['--name', '-n'], help="Graph name")
        c.argument('throughput', type=int, help='The throughput Gremlin graph (RU/s).')
        c.argument('max_throughput', max_throughput_type)

    with self.argument_context('cosmosdb table throughput') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('table_name', options_list=['--name', '-n'], help="Table name")
        c.argument('throughput', type=int, help='The throughput of Table (RU/s).')
        c.argument('max_throughput', max_throughput_type)

    for scope in ['sql database throughput migrate', 'sql container throughput migrate',
                  'gremlin database throughput migrate', 'gremlin graph throughput migrate',
                  'cassandra table throughput migrate', 'cassandra keyspace throughput migrate',
                  'mongodb collection throughput migrate', 'mongodb database throughput migrate',
                  'table throughput migrate']:
        with self.argument_context('cosmosdb {}'.format(scope)) as c:
            c.argument('throughput_type', throughput_type)

    account_name_type = CLIArgumentType(options_list=['--account-name', '-a'], help="Cosmosdb account name.")

    # SQL role definition
    with self.argument_context('cosmosdb sql role definition') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('role_definition_id', options_list=['--id', '-i'], validator=validate_role_definition_id, help="Unique ID for the Role Definition.")
        c.argument('role_definition_body', options_list=['--body', '-b'], validator=validate_role_definition_body, completer=FilesCompleter(), help="Role Definition body with Id (Optional for create), DataActions or Permissions, Type (Default is CustomRole), and AssignableScopes.  You can enter it as a string or as a file, e.g., --body @rdbody-file.json or " + SQL_ROLE_DEFINITION_EXAMPLE)

    # SQL role assignment
    with self.argument_context('cosmosdb sql role assignment') as c:
        c.argument('account_name', account_name_type, id_part=None)
        c.argument('role_assignment_id', options_list=['--role-assignment-id', '-i'], validator=validate_role_assignment_id, help="Optional for Create. Unique ID for the Role Assignment. If not provided, a new GUID will be used.")
        c.argument('role_definition_id', options_list=['--role-definition-id', '-d'], validator=validate_fully_qualified_role_definition_id, help="Unique ID of the Role Definition that this Role Assignment refers to.")
        c.argument('role_definition_name', options_list=['--role-definition-name', '-n'], help="Unique Name of the Role Definition that this Role Assignment refers to. Eg. 'Contoso Reader Role'.")
        c.argument('scope', validator=validate_scope, options_list=['--scope', '-s'], help="Data plane resource path at which this Role Assignment is being granted.")
        c.argument('principal_id', options_list=['--principal-id', '-p'], help="AAD Object ID of the principal to which this Role Assignment is being granted.")


from util import Util
from treatment import Treatment

utility = Util()
file = utility.read_file('mega.txt')  # file = Lista de strings

aux_file = []
for index in file:
    aux_file.append(index.replace(',\n', '').split(','))

all_lottery = aux_file
# all_lottery stores all result of lottery as a list of lists

del aux_file

numbers_frequency = {key: 0 for key in range(1,61)}

for x in range(1,61):
    for lottery in all_lottery:
        for number in lottery:
            if number == str(x):
                numbers_frequency[x] += 1

'''
print(len(all_lottery*6))
total = 0
for key in numbers_frequency.keys():
    total += numbers_frequency.get(key)
print(total)
print(numbers_frequency)
'''

position = 1
numbers_position = {}
for item in sorted(numbers_frequency, key=numbers_frequency.get, reverse=True):
    # print('Número sorteado:', item, ' \tQtd de vezes',
    #  numbers_frequency[item], '\tPosição:', position)
    numbers_position.update({item: position})
    position += 1

treatment = Treatment()
even_quantity = treatment.how_many_pairs(all_lottery)

neighbors_1 = treatment.neighborhood(all_lottery, 1)
neighbors_2 = treatment.neighborhood(all_lottery, 2)
neighbors_3 = treatment.neighborhood(all_lottery, 3)
neighbors_4 = treatment.neighborhood(all_lottery, 4)
neighbors_5 = treatment.neighborhood(all_lottery, 5)

print('Quantidade de pares:\n', even_quantity)
print('\n\n Distância 1\n', neighbors_1)
print('\n\n Distância 2\n', neighbors_2)
print('\n\n Distância 3\n', neighbors_3)
print('\n\n Distância 4\n', neighbors_4)
print('\n\n Distância 5\n', neighbors_5)


import json
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.sites.shortcuts import get_current_site
from django.core.mail import EmailMessage
from django.db.models import Q
from django.forms.models import modelformset_factory
from django.http import HttpResponseRedirect, JsonResponse, HttpResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.template.loader import render_to_string
from django.urls import reverse
from django.views.generic import (
    CreateView, DetailView, ListView, TemplateView, View)

from accounts.models import Account, Tags
from common.models import User, Comment, Attachments, APISettings
from common.utils import LEAD_STATUS, LEAD_SOURCE, COUNTRIES
from common import status
from contacts.models import Contact
from leads.models import Lead
from leads.forms import LeadCommentForm, LeadForm, LeadAttachmentForm, LeadListForm
from planner.models import Event, Reminder
from planner.forms import ReminderForm
from leads.tasks import send_lead_assigned_emails
from django.core.exceptions import PermissionDenied
from common.tasks import send_email_user_mentions
from leads.tasks import send_email_to_assigned_user, create_lead_from_file
from common.access_decorators_mixins import (
    sales_access_required, marketing_access_required, SalesAccessRequiredMixin, MarketingAccessRequiredMixin)
from teams.models import Teams

class LeadListView(SalesAccessRequiredMixin, LoginRequiredMixin, TemplateView):
    model = Lead
    context_object_name = "lead_obj"
    template_name = "leads.html"

    def get_queryset(self):
        queryset = self.model.objects.all().exclude(status='converted')
        if (self.request.user.role != "ADMIN" and not
                self.request.user.is_superuser):
            queryset = queryset.filter(
                Q(assigned_to__in=[self.request.user]) |
                Q(created_by=self.request.user))

        if self.request.GET.get('tag', None):
            queryset = queryset.filter(tags__in = self.request.GET.getlist('tag'))

        request_post = self.request.POST
        if request_post:
            if request_post.get('name'):
                queryset = queryset.filter(
                    Q(first_name__icontains=request_post.get('name')) &
                    Q(last_name__icontains=request_post.get('name')))
            if request_post.get('city'):
                queryset = queryset.filter(
                    city__icontains=request_post.get('city'))
            if request_post.get('email'):
                queryset = queryset.filter(
                    email__icontains=request_post.get('email'))
            if request_post.get('status'):
                queryset = queryset.filter(status=request_post.get('status'))
            if request_post.get('tag'):
                queryset = queryset.filter(tags__in=request_post.getlist('tag'))
            if request_post.get('source'):
                queryset = queryset.filter(source=request_post.get('source'))
            if request_post.getlist('assigned_to'):
                queryset = queryset.filter(
                    assigned_to__id__in=request_post.getlist('assigned_to'))
        return queryset.distinct()

    def get_context_data(self, **kwargs):
        context = super(LeadListView, self).get_context_data(**kwargs)
        # context["lead_obj"] = self.get_queryset()
        open_leads = self.get_queryset().exclude(status='closed')
        close_leads = self.get_queryset().filter(status='closed')
        context["status"] = LEAD_STATUS
        context["open_leads"] = open_leads
        context["close_leads"] = close_leads
        context["per_page"] = self.request.POST.get('per_page')
        context["source"] = LEAD_SOURCE
        context["users"] = User.objects.filter(
            is_active=True).order_by('email')
        context["assignedto_list"] = [
            int(i) for i in self.request.POST.getlist('assigned_to', []) if i]
        context["request_tags"] = self.request.POST.getlist('tag')

        search = True if (
            self.request.POST.get('name') or self.request.POST.get('city') or
            self.request.POST.get('email') or self.request.POST.get('tag') or
            self.request.POST.get('status') or
            self.request.POST.get('source') or
            self.request.POST.get('assigned_to')
        ) else False

        context["search"] = search

        tag_ids = list(set(Lead.objects.values_list('tags', flat=True)))
        context["tags"] = Tags.objects.filter(id__in=tag_ids)

        tab_status = 'Open'
        if self.request.POST.get('tab_status'):
            tab_status = self.request.POST.get('tab_status')
        context['tab_status'] = tab_status

        return context

    def post(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)
        return self.render_to_response(context)

@login_required
@sales_access_required
def create_lead(request):
    template_name = "create_lead.html"
    users = []
    if request.user.role == 'ADMIN' or request.user.is_superuser:
        users = User.objects.filter(is_active=True).order_by('email')
    elif request.user.google.all():
        users = []
    else:
        users = User.objects.filter(role='ADMIN').order_by('email')
    form = LeadForm(assigned_to=users)

    if request.POST:
        form = LeadForm(request.POST, request.FILES, assigned_to=users)
        if form.is_valid():
            lead_obj = form.save(commit=False)
            lead_obj.created_by = request.user
            lead_obj.save()
            if request.POST.get('tags', ''):
                tags = request.POST.get("tags")
                splitted_tags = tags.split(",")
                for t in splitted_tags:
                    tag = Tags.objects.filter(name=t)
                    if tag:
                        tag = tag[0]
                    else:
                        tag = Tags.objects.create(name=t)
                    lead_obj.tags.add(tag)
            if request.POST.getlist('assigned_to', []):
                lead_obj.assigned_to.add(*request.POST.getlist('assigned_to'))
                assigned_to_list = request.POST.getlist('assigned_to')
                # current_site = get_current_site(request)
                # recipients = assigned_to_list
                # send_email_to_assigned_user.delay(recipients, lead_obj.id, domain=current_site.domain,
                #     protocol=request.scheme)
                # for assigned_to_user in assigned_to_list:
                #     user = get_object_or_404(User, pk=assigned_to_user)
                #     mail_subject = 'Assigned to lead.'
                #     message = render_to_string(
                #         'assigned_to/leads_assigned.html', {
                #             'user': user,
                #             'domain': current_site.domain,
                #             'protocol': request.scheme,
                #             'lead': lead_obj
                #         })
                #     email = EmailMessage(
                #         mail_subject, message, to=[user.email])
                #     email.content_subtype = "html"
                #     email.send()
            if request.POST.getlist('teams', []):
                user_ids = Teams.objects.filter(id__in=request.POST.getlist('teams')).values_list('users', flat=True)
                assinged_to_users_ids = lead_obj.assigned_to.all().values_list('id', flat=True)
                for user_id in user_ids:
                    if user_id not in assinged_to_users_ids:
                        lead_obj.assigned_to.add(user_id)

            current_site = get_current_site(request)
            recipients = list(lead_obj.assigned_to.all().values_list('id', flat=True))
            send_email_to_assigned_user.delay(recipients, lead_obj.id, domain=current_site.domain,
                protocol=request.scheme)

            if request.FILES.get('lead_attachment'):
                attachment = Attachments()
                attachment.created_by = request.user
                attachment.file_name = request.FILES.get(
                    'lead_attachment').name
                attachment.lead = lead_obj
                attachment.attachment = request.FILES.get('lead_attachment')
                attachment.save()

            if request.POST.get('status') == "converted":
                account_object = Account.objects.create(
                    created_by=request.user, name=lead_obj.account_name,
                    email=lead_obj.email, phone=lead_obj.phone,
                    description=request.POST.get('description'),
                    website=request.POST.get('website'),
                )
                account_object.billing_address_line = lead_obj.address_line
                account_object.billing_street = lead_obj.street
                account_object.billing_city = lead_obj.city
                account_object.billing_state = lead_obj.state
                account_object.billing_postcode = lead_obj.postcode
                account_object.billing_country = lead_obj.country
                for tag in lead_obj.tags.all():
                    account_object.tags.add(tag)

                if request.POST.getlist('assigned_to', []):
                    # account_object.assigned_to.add(*request.POST.getlist('assigned_to'))
                    assigned_to_list = request.POST.getlist('assigned_to')
                    current_site = get_current_site(request)
                    recipients = assigned_to_list
                    send_email_to_assigned_user.delay(recipients, lead_obj.id, domain=current_site.domain,
                        protocol=request.scheme)
                    # for assigned_to_user in assigned_to_list:
                    #     user = get_object_or_404(User, pk=assigned_to_user)
                    #     mail_subject = 'Assigned to account.'
                    #     message = render_to_string(
                    #         'assigned_to/account_assigned.html', {
                    #             'user': user,
                    #             'domain': current_site.domain,
                    #             'protocol': request.scheme,
                    #             'account': account_object
                    #         })
                    #     email = EmailMessage(
                    #         mail_subject, message, to=[user.email])
                    #     email.content_subtype = "html"
                    #     email.send()

                account_object.save()
            success_url = reverse('leads:list')
            if request.POST.get("savenewform"):
                success_url = reverse("leads:add_lead")
            return JsonResponse({'error': False, 'success_url': success_url})
        return JsonResponse({'error': True, 'errors': form.errors})
    context = {}
    context["lead_form"] = form
    context["accounts"] = Account.objects.filter(status="open")
    context["users"] = users
    context["countries"] = COUNTRIES
    context["status"] = LEAD_STATUS
    context["source"] = LEAD_SOURCE
    context["assignedto_list"] = [
        int(i) for i in request.POST.getlist('assigned_to', []) if i]

    return render(request, template_name, context)

class LeadDetailView(SalesAccessRequiredMixin, LoginRequiredMixin, DetailView):
    model = Lead
    context_object_name = "lead_record"
    template_name = "view_leads.html"

    def get_context_data(self, **kwargs):
        context = super(LeadDetailView, self).get_context_data(**kwargs)
        user_assgn_list = [
            assigned_to.id for assigned_to in context['object'].assigned_to.all()]
        if self.request.user == context['object'].created_by:
            user_assgn_list.append(self.request.user.id)
        if (self.request.user.role != "ADMIN" and not
                self.request.user.is_superuser):
            if self.request.user.id not in user_assgn_list:
                raise PermissionDenied
        comments = Comment.objects.filter(
            lead__id=self.object.id).order_by('-id')
        attachments = Attachments.objects.filter(
            lead__id=self.object.id).order_by('-id')
        events = Event.objects.filter(
            Q(created_by=self.request.user) | Q(updated_by=self.request.user)
        ).filter(attendees_leads=context["lead_record"])
        meetings = events.filter(event_type='Meeting').order_by('-id')
        calls = events.filter(event_type='Call').order_by('-id')
        RemindersFormSet = modelformset_factory(
            Reminder, form=ReminderForm, can_delete=True)
        reminder_form_set = RemindersFormSet({
            'form-TOTAL_FORMS': '1',
            'form-INITIAL_FORMS': '0',
            'form-MAX_NUM_FORMS': '10',
        })

        assigned_data = []
        for each in context['lead_record'].assigned_to.all():
            assigned_dict = {}
            assigned_dict['id'] = each.id
            assigned_dict['name'] = each.email
            assigned_data.append(assigned_dict)

        if self.request.user.is_superuser or self.request.user.role == 'ADMIN':
            users_mention = list(User.objects.filter(is_active=True).values('username'))
        elif self.request.user != context['object'].created_by:
            users_mention = [{'username': context['object'].created_by.username}]
        else:
            users_mention = list(context['object'].assigned_to.all().values('username'))

        context.update({
            "attachments": attachments, "comments": comments,
            "status": LEAD_STATUS, "countries": COUNTRIES,
            "reminder_form_set": reminder_form_set,
            "meetings": meetings, "calls": calls,
            "users_mention": users_mention,
            "assigned_data": json.dumps(assigned_data)})
        return context

@login_required
@sales_access_required
def update_lead(request, pk):
    lead_record = Lead.objects.filter(pk=pk).first()
    template_name = "create_lead.html"
    users = []
    if request.user.role == 'ADMIN' or request.user.is_superuser:
        users = User.objects.filter(is_active=True).order_by('email')
    else:
        users = User.objects.filter(role='ADMIN').order_by('email')
    status = request.GET.get('status', None)
    initial = {}
    if status and status == "converted":
        error = "This field is required."
        lead_record.status = "converted"
        initial.update({
            "status": status, "lead": lead_record.id})
    error = ""
    form = LeadForm(instance=lead_record, initial=initial, assigned_to=users)

    if request.POST:
        form = LeadForm(request.POST, request.FILES,
                        instance=lead_record,
                        initial=initial, assigned_to=users)

        if request.POST.get('status') == "converted":
            form.fields['account_name'].required = True
            form.fields['email'].required = True
        else:
            form.fields['account_name'].required = False
            form.fields['email'].required = False
        if form.is_valid():
            assigned_to_ids = lead_record.assigned_to.all().values_list(
                'id', flat=True)
            lead_obj = form.save(commit=False)
            lead_obj.save()
            lead_obj.tags.clear()
            all_members_list = []
            if request.POST.get('tags', ''):
                tags = request.POST.get("tags")
                splitted_tags = tags.split(",")
                for t in splitted_tags:
                    tag = Tags.objects.filter(name=t)
                    if tag:
                        tag = tag[0]
                    else:
                        tag = Tags.objects.create(name=t)
                    lead_obj.tags.add(tag)
            if request.POST.getlist('assigned_to', []):
                if request.POST.get('status') != "converted":

                    current_site = get_current_site(request)

                    assigned_form_users = form.cleaned_data.get(
                        'assigned_to').values_list('id', flat=True)
                    all_members_list = list(
                        set(list(assigned_form_users)) -
                        set(list(assigned_to_ids)))
                    # current_site = get_current_site(request)
                    # recipients = all_members_list
                    # send_email_to_assigned_user.delay(recipients, lead_obj.id, domain=current_site.domain,
                    #     protocol=request.scheme)
                    # if all_members_list:
                    #     for assigned_to_user in all_members_list:
                    #         user = get_object_or_404(User, pk=assigned_to_user)
                    #         mail_subject = 'Assigned to lead.'
                    #         message = render_to_string(
                    #             'assigned_to/leads_assigned.html', {
                    #                 'user': user,
                    #                 'domain': current_site.domain,
                    #                 'protocol': request.scheme,
                    #                 'lead': lead_obj
                    #             })
                    #         email = EmailMessage(
                    #             mail_subject, message, to=[user.email])
                    #         email.content_subtype = "html"
                    #         email.send()

                lead_obj.assigned_to.clear()
                lead_obj.assigned_to.add(*request.POST.getlist('assigned_to'))
            else:
                lead_obj.assigned_to.clear()

            if request.POST.getlist('teams', []):
                user_ids = Teams.objects.filter(id__in=request.POST.getlist('teams')).values_list('users', flat=True)
                assinged_to_users_ids = lead_obj.assigned_to.all().values_list('id', flat=True)
                for user_id in user_ids:
                    if user_id not in assinged_to_users_ids:
                        lead_obj.assigned_to.add(user_id)

            current_site = get_current_site(request)
            recipients = list(lead_obj.assigned_to.all().values_list('id', flat=True))
            send_email_to_assigned_user.delay(recipients, lead_obj.id, domain=current_site.domain,
                protocol=request.scheme)

            if request.FILES.get('lead_attachment'):
                attachment = Attachments()
                attachment.created_by = request.user
                attachment.file_name = request.FILES.get(
                    'lead_attachment').name
                attachment.lead = lead_obj
                attachment.attachment = request.FILES.get('lead_attachment')
                attachment.save()

            if request.POST.get('status') == "converted":
                account_object = Account.objects.create(
                    created_by=request.user, name=lead_obj.account_name,
                    email=lead_obj.email, phone=lead_obj.phone,
                    description=request.POST.get('description'),
                    website=request.POST.get('website'),
                    lead=lead_obj
                )
                account_object.billing_address_line = lead_obj.address_line
                account_object.billing_street = lead_obj.street
                account_object.billing_city = lead_obj.city
                account_object.billing_state = lead_obj.state
                account_object.billing_postcode = lead_obj.postcode
                account_object.billing_country = lead_obj.country
                for tag in lead_obj.tags.all():
                    account_object.tags.add(tag)
                if request.POST.getlist('assigned_to', []):
                    # account_object.assigned_to.add(*request.POST.getlist('assigned_to'))
                    assigned_to_list = request.POST.getlist('assigned_to')
                    current_site = get_current_site(request)
                    recipients = assigned_to_list
                    send_email_to_assigned_user.delay(recipients, lead_obj.id, domain=current_site.domain,
                        protocol=request.scheme)
                    # current_site = get_current_site(request)
                    # for assigned_to_user in assigned_to_list:
                    #     user = get_object_or_404(User, pk=assigned_to_user)
                    #     mail_subject = 'Assigned to account.'
                    #     message = render_to_string(
                    #         'assigned_to/account_assigned.html', {
                    #             'user': user,
                    #             'domain': current_site.domain,
                    #             'protocol': request.scheme,
                    #             'account': account_object
                    #         })
                    #     email = EmailMessage(
                    #         mail_subject, message, to=[user.email])
                    #     email.content_subtype = "html"
                    #     email.send()

                for comment in lead_obj.leads_comments.all():
                    comment.account = account_object
                    comment.save()
                account_object.save()
            status = request.GET.get('status', None)
            success_url = reverse('leads:list')
            if status:
                success_url = reverse('accounts:list')
            return JsonResponse({'error': False, 'success_url': success_url})
        return JsonResponse({'error': True, 'errors': form.errors})
    context = {}
    context["lead_obj"] = lead_record
    user_assgn_list = [
        assigned_to.id for assigned_to in lead_record.assigned_to.all()]
    if request.user == lead_record.created_by:
        user_assgn_list.append(request.user.id)
    if request.user.role != "ADMIN" and not request.user.is_superuser:
        if request.user.id not in user_assgn_list:
            raise PermissionDenied

    context["lead_form"] = form
    context["accounts"] = Account.objects.filter(status="open")
    context["users"] = users
    context["countries"] = COUNTRIES
    context["status"] = LEAD_STATUS
    context["source"] = LEAD_SOURCE
    context["error"] = error
    context["assignedto_list"] = [
        int(i) for i in request.POST.getlist('assigned_to', []) if i]

    return render(request, template_name, context)

class DeleteLeadView(SalesAccessRequiredMixin, LoginRequiredMixin, View):

    def get(self, request, *args, **kwargs):
        return self.post(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        self.object = get_object_or_404(Lead, id=kwargs.get("pk"))
        if (
            self.request.user.role == "ADMIN" or
            self.request.user.is_superuser or
            self.request.user == self.object.created_by
        ):
            self.object.delete()
            return redirect("leads:list")
        raise PermissionDenied

def convert_lead(request, pk):
    lead_obj = get_object_or_404(Lead, id=pk)
    if lead_obj.account_name and lead_obj.email:
        lead_obj.status = 'converted'
        lead_obj.save()
        account_object = Account.objects.create(
            created_by=request.user, name=lead_obj.account_name,
            email=lead_obj.email, phone=lead_obj.phone,
            description=lead_obj.description,
            website=lead_obj.website,
            billing_address_line=lead_obj.address_line,
            billing_street=lead_obj.street,
            billing_city=lead_obj.city,
            billing_state=lead_obj.state,
            billing_postcode=lead_obj.postcode,
            billing_country=lead_obj.country,
            lead=lead_obj
        )
        contacts_list = lead_obj.contacts.all().values_list('id', flat=True)
        account_object.contacts.add(*contacts_list)
        account_obj = account_object.save()
        current_site = get_current_site(request)
        for assigned_to_user in lead_obj.assigned_to.all().values_list(
                'id', flat=True):
            user = get_object_or_404(User, pk=assigned_to_user)
            mail_subject = 'Assigned to account.'
            message = render_to_string('assigned_to/account_assigned.html', {
                'user': user,
                'domain': current_site.domain,
                'protocol': request.scheme,
                'account': account_object
            })
            email = EmailMessage(mail_subject, message, to=[user.email])
            email.content_subtype = "html"
            email.send()
        return redirect("accounts:list")

    return HttpResponseRedirect(
        reverse('leads:edit_lead', kwargs={
            'pk': lead_obj.id}) + '?status=converted')

class AddCommentView(LoginRequiredMixin, CreateView):
    model = Comment
    form_class = LeadCommentForm
    http_method_names = ["post"]

    def post(self, request, *args, **kwargs):
        self.object = None
        self.lead = get_object_or_404(Lead, id=request.POST.get('leadid'))
        if (
            request.user in self.lead.assigned_to.all() or
            request.user == self.lead.created_by or
            request.user.is_superuser or
            request.user.role == 'ADMIN'
        ):
            form = self.get_form()
            if form.is_valid():
                return self.form_valid(form)

            return self.form_invalid(form)

        data = {'error': "You don't have permission to comment."}
        return JsonResponse(data)

    def form_valid(self, form):
        comment = form.save(commit=False)
        comment.commented_by = self.request.user
        comment.lead = self.lead
        comment.save()
        comment_id = comment.id
        current_site = get_current_site(self.request)
        send_email_user_mentions.delay(comment_id, 'leads', domain=current_site.domain,
            protocol=self.request.scheme)
        return JsonResponse({
            "comment_id": comment.id, "comment": comment.comment,
            "commented_on": comment.commented_on,
            "commented_on_arrow": comment.commented_on_arrow,
            "commented_by": comment.commented_by.email
        })

    def form_invalid(self, form):
        return JsonResponse({"error": form['comment'].errors})

class UpdateCommentView(LoginRequiredMixin, View):
    http_method_names = ["post"]

    def post(self, request, *args, **kwargs):
        self.comment_obj = get_object_or_404(
            Comment, id=request.POST.get("commentid"))
        if request.user == self.comment_obj.commented_by:
            form = LeadCommentForm(request.POST, instance=self.comment_obj)
            if form.is_valid():
                return self.form_valid(form)

            return self.form_invalid(form)

        data = {'error': "You don't have permission to edit this comment."}
        return JsonResponse(data)

    def form_valid(self, form):
        self.comment_obj.comment = form.cleaned_data.get("comment")
        self.comment_obj.save(update_fields=["comment"])
        comment_id = self.comment_obj.id
        current_site = get_current_site(self.request)
        send_email_user_mentions.delay(comment_id, 'leads', domain=current_site.domain,
            protocol=self.request.scheme)
        return JsonResponse({
            "commentid": self.comment_obj.id,
            "comment": self.comment_obj.comment,
        })

    def form_invalid(self, form):
        return JsonResponse({"error": form['comment'].errors})

class DeleteCommentView(LoginRequiredMixin, View):

    def post(self, request, *args, **kwargs):
        self.object = get_object_or_404(
            Comment, id=request.POST.get("comment_id"))
        if request.user == self.object.commented_by:
            self.object.delete()
            data = {"cid": request.POST.get("comment_id")}
            return JsonResponse(data)

        data = {'error': "You don't have permission to delete this comment."}
        return JsonResponse(data)

class GetLeadsView(LoginRequiredMixin, ListView):
    model = Lead
    context_object_name = "leads"
    template_name = "leads_list.html"

class AddAttachmentsView(LoginRequiredMixin, CreateView):
    model = Attachments
    form_class = LeadAttachmentForm
    http_method_names = ["post"]

    def post(self, request, *args, **kwargs):
        self.object = None
        self.lead = get_object_or_404(Lead, id=request.POST.get('leadid'))
        if (
                request.user in self.lead.assigned_to.all() or
                request.user == self.lead.created_by or
                request.user.is_superuser or
                request.user.role == 'ADMIN'
        ):
            form = self.get_form()
            if form.is_valid():
                return self.form_valid(form)
            return self.form_invalid(form)

        data = {'error': "You don't have permission to add attachment."}
        return JsonResponse(data)

    def form_valid(self, form):
        attachment = form.save(commit=False)
        attachment.created_by = self.request.user
        attachment.file_name = attachment.attachment.name
        attachment.lead = self.lead
        attachment.save()
        return JsonResponse({
            "attachment_id": attachment.id,
            "attachment": attachment.file_name,
            "attachment_url": attachment.attachment.url,
            "created_on": attachment.created_on,
            "created_on_arrow": attachment.created_on_arrow,
            "created_by": attachment.created_by.email,
            "download_url": reverse(
                'common:download_attachment', kwargs={'pk': attachment.id}),
            "attachment_display": attachment.get_file_type_display(),
            "file_type": attachment.file_type()
        })

    def form_invalid(self, form):
        return JsonResponse({"error": form['attachment'].errors})

class DeleteAttachmentsView(LoginRequiredMixin, View):

    def post(self, request, *args, **kwargs):
        self.object = get_object_or_404(
            Attachments, id=request.POST.get("attachment_id"))
        if (
            request.user == self.object.created_by or
            request.user.is_superuser or
            request.user.role == 'ADMIN'
        ):
            self.object.delete()
            data = {"aid": request.POST.get("attachment_id")}
            return JsonResponse(data)

        data = {'error':
                "You don't have permission to delete this attachment."}
        return JsonResponse(data)

def create_lead_from_site(request):
    if request.method == "POST":
        # ip_addres = get_client_ip(request)
        # website_address = request.scheme + '://' + ip_addres
        api_key = request.POST.get('apikey')
        # api_setting = APISettings.objects.filter(
        #     website=website_address, apikey=api_key).first()
        api_setting = APISettings.objects.filter(apikey=api_key).first()
        if not api_setting:
            return JsonResponse({
                'error': True,
                'message':
                "You don't have permission, please contact the admin!."},
                status=status.HTTP_400_BAD_REQUEST)

        if (api_setting and request.POST.get("email") and
                request.POST.get("full_name")):
            # user = User.objects.filter(is_admin=True, is_active=True).first()
            user = api_setting.created_by
            lead = Lead.objects.create(
                title=request.POST.get("full_name"),
                status="assigned", source=api_setting.website,
                description=request.POST.get("message"),
                email=request.POST.get("email"),
                phone=request.POST.get("phone"),
                is_active=True, created_by=user)
            lead.assigned_to.add(user)
            # Send Email to Assigned Users
            site_address = request.scheme + '://' + request.META['HTTP_HOST']
            send_lead_assigned_emails.delay(lead.id, [user.id], site_address)
            # Create Contact
            contact = Contact.objects.create(
                first_name=request.POST.get("full_name"),
                email=request.POST.get("email"),
                phone=request.POST.get("phone"),
                description=request.POST.get("message"), created_by=user,
                is_active=True)
            contact.assigned_to.add(user)

            lead.contacts.add(contact)

            return JsonResponse({'error': False,
                                 'message': "Lead Created sucessfully."},
                                status=status.HTTP_201_CREATED)
        return JsonResponse({'error': True, 'message': "In-valid data."},
                            status=status.HTTP_400_BAD_REQUEST)
    return JsonResponse({
        'error': True, 'message': "In-valid request method."},
        status=status.HTTP_400_BAD_REQUEST)

@login_required
@sales_access_required
def update_lead_tags(request, pk):
    lead = get_object_or_404(Lead, pk=pk)
    if request.user == lead.created_by or request.user.role == 'ADMIN' or request.user.is_superuser:
        lead.tags.clear()
        if request.POST.get('tags', ''):
            tags = request.POST.get("tags")
            splitted_tags = tags.split(",")
            for t in splitted_tags:
                tag = Tags.objects.filter(name=t)
                if tag:
                    tag = tag[0]
                else:
                    tag = Tags.objects.create(name=t)
                lead.tags.add(tag)
    else:
        raise PermissionDenied
    return HttpResponseRedirect(request.POST.get('full_path'))

@login_required
@sales_access_required
def remove_lead_tag(request):
    data = {}
    lead_id = request.POST.get('lead')
    tag_id = request.POST.get('tag')
    lead = get_object_or_404(Lead, pk=lead_id)
    if request.user == lead.created_by or request.user.role == 'ADMIN' or request.user.is_superuser:
        lead.tags.remove(tag_id)
        data = {'data':'Tag Removed'}
    else:
        data = {'error': "You don't have permission to delete this tag."}
    return JsonResponse(data)

@login_required
@sales_access_required
def upload_lead_csv_file(request):
    if request.method == 'POST':
        lead_form = LeadListForm(request.POST, request.FILES)
        if lead_form.is_valid():
            create_lead_from_file.delay(
                    lead_form.validated_rows, lead_form.invalid_rows, request.user.id)
            return JsonResponse({'error': False, 'data': lead_form.data},
                status=status.HTTP_201_CREATED)
        else:
            return JsonResponse({'error': True, 'errors': lead_form.errors},
                status=status.HTTP_200_OK)

def sample_lead_file(request):
    sample_data = [
        'title,first name,last name,website,phone,email,address\n',
        'lead1,john,doe,www.example.com,911234567890,user1@email.com,address for lead1\n',
        'lead2,jane,doe,www.website.com,911234567891,user2@email.com,address for lead2\n',
        'lead3,joe,doe,www.test.com,911234567892,user3@email.com,address for lead3\n',
        'lead4,john,doe,www.sample.com,911234567893,user4@email.com,address for lead4\n',
    ]
    response = HttpResponse(
        sample_data, content_type='text/plain')
    response['Content-Disposition'] = 'attachment; filename={}'.format(
        'sample_data.csv')
    return response


"""
suomensaa.py
Made by rolle
Updated 20200628
"""
import sopel.module
from urllib.request import urlopen
import lxml.etree
from lxml import etree
import lxml.html
import requests
import datetime
import os
import json
from pprint import pprint

# paikkojen tiedosto
places_file = '/home/rolle/.sopel/modules/paikat.json'
# nimimerkkien paikat muistissa
places_cfg = {}

# Ladataan tiedostosta tallennetut paikat
def load_cfg():
  # NOTE: menis nätimmin class propertyillä tmv. toki
  global places_file
  global places_cfg

  if os.path.exists(places_file):
    filehandle = open(places_file, 'r')
    places_cfg = json.loads(filehandle.read())
    filehandle.close()

# Asetetaan paikka nimimerkille ja tallennetaan tiedostoon
def set_place(nick, place):
  # NOTE: menis nätimmin class propertyillä tmv. toki
  global places_file
  global places_cfg

  # asetetaan paikka muistiin
  places_cfg[nick] = place

  # tallennetaan tiedostoon
  filehandle = open(places_file, 'w+')
  filehandle.write(json.dumps(places_cfg))
  filehandle.close()

# ladataan paikat heti muistiin
load_cfg()

@sopel.module.commands('asetasää', 'asetakeli')
def asetasaa(bot, trigger):
  if not trigger.group(2):
    bot.say("!asetasää <kaupunki> - Esim. !asetasää Jyväskylä asettaa nimimerkillesi oletuspaikaksi Jyväskylän. Tämän jälkeen pelkkä !sää hakee asetetusta paikasta säätiedot.") #FIXME
    return

  set_place(trigger.nick, trigger.group(2).strip())
  bot.say("Paikka '" + trigger.group(2).strip() + "' asetettu nimimerkin " + trigger.nick +
    " oletuspaikaksi")

@sopel.module.commands('sää', 'keli')

def saa(bot, trigger):

  # vältetään konfliktit asettamalla muuttuja 'paikka' epätodeksi
  place = False

  if not trigger.group(2):

    # tarkistetaan löytyykö nickiltä asetettua paikkaa
    if trigger.nick in places_cfg:
      place = places_cfg[trigger.nick]

    else:
      bot.say("!sää <kaupunki> - Esim. !sää jyväskylä kertoo Jyväskylän sään. Hakee säätiedot Ilmatieteen laitokselta. !asetasää <kaupunki> asettaa oletuspaikan nimimerkillesi jonka jälkeen pelkkä !sää hakee asetetun paikan säätiedot.")
      return

  if not place:
    place = trigger.group(2).strip()

  url = "https://yle.fi/saa/suomi/%s" % place
  url_sunsetsunrise = "http://www.moisio.fi/taivas/aurinko.php?paikka=%s" % place

  # LXML Xpath based scraping
  r = requests.get(url, headers={'Accept-Language': 'fi-FI', 'Content-type': 'text/html;charset=UTF-8', "accept-encoding": "gzip, deflate"})
  r.encoding == 'ISO-8859-1' and not 'ISO-8859-1' in r.headers.get('Content-Type', '')
  root = lxml.html.fromstring(r.content)

  if place == 'jyväskylä':
    url_jkl = "http://weather.jyu.fi"
    r_jkl = requests.get(url_jkl)
    root_jkl = lxml.html.fromstring(r_jkl.content)

    #try:

    # http://weather.jyu.fi/
    place_exact_get = root_jkl.xpath('//*[@id="content"]/fieldset/legend')
    place_exact = place_exact_get[0].text.strip()
    temperature_get = root_jkl.xpath('//*[@id="table-a"]/tbody/tr[1]/td[2]')
    temperature = temperature_get[0].text.strip()
    time_get = root_jkl.xpath('//*[@id="c2"]/text()')

    # Nämä samat kuin elsen jälkeen
    rain_probability_get = root.xpath('//*[@id="pointdata-container"]/div[2]/div[2]/div[1]/span/span[1]/span[3]')
    temperature_nextday_get = root.xpath('//*[@id="dailydata"]/li[1]/span[2]/span[5]/span[3]/span[1]/span[2]')
    textweather_get = root.xpath('//*[@id="pointdata-container"]/div[2]/div[1]/div[1]/span/span')
    textweather = textweather_get[0].text.strip().encode('latin-1').decode(encoding='utf-8',errors='strict')
    nextday_text_get = root.xpath('//*[@id="dailydata"]/li[1]/span[2]/span[5]/span[2]/span/span')
    feelslike_get = root.xpath('//*[@id="pointdata-container"]/div[2]/div[1]/div[2]/span/text()')
    precipitation_amount_get = root.xpath('//*[@id="pointdata-container"]/div[2]/div[2]/div[1]/span/span[1]/span[5]/strong')
    temperature_nextday = temperature_nextday_get[0].text.strip()
    rain_probability = rain_probability_get[0].text.strip()
    nextday_text = nextday_text_get[0].text.strip().encode('latin-1').decode(encoding='utf-8',errors='strict')
    textweather = textweather_get[0].text.strip().encode('latin-1').decode(encoding='utf-8',errors='strict')
    time = time_get[0]
    feelslike = feelslike_get[0]
    precipitation_amount = precipitation_amount_get[0].text.strip()

    bot.say('\x02Jyväskylä, ' + place_exact + '\x0F: ' + temperature + ' (' + textweather + ', ' + feelslike + '), mitattu ' + time + '. Sateen todennäköisyys: ' + rain_probability + '%, määrä: ' + precipitation_amount + '. Huomispäiväksi luvattu ' + temperature_nextday + ' (' + nextday_text + ').')

    #except:
      #bot.say('Error, tilt, nyt bugaa! Sijainnin \x02' + place.capitalize() + '\x0F säätä ei saatu haettua. Heitä ihmeessä pull requestia, jos tiedät miten tämä korjataan. Sään tarjoilee: https://github.com/pulinairc/kummitus/blob/master/modules/suomensaa.py')

  elif place == 'rolle':

    url_rolle = "https://ruuvirawdata.peikko.us/ruuvidata.txt"
    temps = urlopen(url_rolle).read().decode("utf-8")
    bot.say('\x02Jyväskylä, Rollen ja mustikkasopan koti\x0F: ' + temps + '')

  else:

    try:
      # Pääinputin value
      city = root.xpath('//*[@id="searchField"]/@value')[0].encode('latin-1').decode(encoding='utf-8',errors='strict')

      # "Säätila tänään klo XX:XX" XPath
      time_get = root.xpath('//*[@id="pointdata-container"]/div[1]/h3')

      # "Sää tulevina päivinä", seuraavan päivän kello 16 kohdalla olevan lämpötiladivin XPath
      temperature_nextday_get = root.xpath('//*[@id="dailydata"]/li[1]/span[2]/span[5]/span[3]/span[1]/span[2]')

      # Sateen todennäköisyys
      rain_probability_get = root.xpath('//*[@id="pointdata-container"]/div[2]/div[2]/div[1]/span/span[1]/span[3]')

      # "Sää tulevina päivinä", seuraavan päivän kello 16 kohdalla olevan kuvan sisällä olevan spanin XPath
      nextday_text_get = root.xpath('//*[@id="dailydata"]/li[1]/span[2]/span[5]/span[2]/span/span')

      # XPath: https://dsh.re/accc8
      temperature_get = root.xpath('//*[@id="pointdata-container"]/div[2]/div[1]/div[2]/div/span[2]')

      # XPath: https://dsh.re/82f509
      feelslike_get = root.xpath('//*[@id="pointdata-container"]/div[2]/div[1]/div[2]/span/text()')

      # XPath: https://dsh.re/0c95b
      textweather_get = root.xpath('//*[@id="pointdata-container"]/div[2]/div[1]/div[1]/span/span')

      # Sademäärä-ennuste
      precipitation_amount_get = root.xpath('//*[@id="pointdata-container"]/div[2]/div[2]/div[1]/span/span[1]/span[5]/strong')

      temperature_nextday = temperature_nextday_get[0].text.strip()
      rain_probability = rain_probability_get[0].text.strip()
      nextday_text = nextday_text_get[0].text.strip().encode('latin-1').decode(encoding='utf-8',errors='strict')
      temperature = temperature_get[0].text.strip()
      textweather = textweather_get[0].text.strip().encode('latin-1').decode(encoding='utf-8',errors='strict')
      time = time_get[0].text.strip().encode('latin-1').decode(encoding='utf-8',errors='strict')
      feelslike = feelslike_get[0]
      precipitation_amount = precipitation_amount_get[0].text.strip()

      bot.say('\x02' + city.capitalize() + '\x0F - ' + time + ': ' + temperature + ' (' + textweather + ', ' + feelslike + '). Sateen todennäköisyys: ' + rain_probability + '%, määrä: ' + precipitation_amount + '. Huomispäiväksi luvattu ' + temperature_nextday + ' (' + nextday_text + ').')

    except:
      bot.say('Error, tilt, nyt bugaa! Sijainnin \x02' + place.capitalize() + '\x0F säätä ei saatu haettua. Heitä ihmeessä pull requestia, jos tiedät miten tämä korjataan. Sään tarjoilee: https://github.com/pulinairc/kummitus/blob/master/modules/suomensaa.py')


import flask
from werkzeug.middleware.proxy_fix import ProxyFix
from flask_login import LoginManager
from flask_mail import Mail
from flask_sqlalchemy import SQLAlchemy

login_manager = LoginManager()
login_manager.session_protection = 'strong'

mail = Mail()
db = SQLAlchemy()

import sampledb.frontend
import sampledb.api
import sampledb.logic
import sampledb.models
import sampledb.models.migrations
import sampledb.config

def create_app():
    app = flask.Flask(__name__)
    app.wsgi_app = ProxyFix(app.wsgi_app)

    app.config.from_object(sampledb.config)

    sampledb.config.check_config(app.config)

    login_manager.init_app(app)
    mail.init_app(app)
    db.init_app(app)
    sampledb.api.server.api.init_app(app)

    app.register_blueprint(sampledb.frontend.frontend)

    login_manager.login_view = 'frontend.sign_in'
    app.jinja_env.globals.update(
        jupyterhub_url=app.config['JUPYTERHUB_URL'],
        signout_form=sampledb.frontend.users_forms.SignoutForm,
        service_name=app.config['SERVICE_NAME'],
        service_description=app.config['SERVICE_DESCRIPTION'],
        service_imprint=app.config['SERVICE_IMPRINT'],
        service_privacy_policy=app.config['SERVICE_PRIVACY_POLICY'],
        ldap_name=app.config['LDAP_NAME'],
        contact_email=app.config['CONTACT_EMAIL']
    )
    app.jinja_env.filters.update(sampledb.frontend.utils.jinja_filter.filters)

    sampledb.logic.files.FILE_STORAGE_PATH = app.config['FILE_STORAGE_PATH']

    with app.app_context():
        db.metadata.create_all(bind=db.engine)
        sampledb.models.Objects.bind = db.engine
        sampledb.models.migrations.run(db)

    return app


#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# Author: Erick
import json, os

from PIL import Image

import oss2

from django.core.files.storage import Storage
from django.utils.six.moves.urllib.parse import urljoin
from django.utils.encoding import filepath_to_uri

class UploadImageOssStorage():
    def __init__(self, bucket_name):
        self.bucket_name = bucket_name

        self.access_key_id = "LTAIfdXXXXXXXX"
        self.access_key_secret = "XXXXXXXXXX"
        # bucket_name = "walkingtkk-suggestion"
        self.endpoint = "oss-cn-shenzhen.aliyuncs.com"

        self.bucket = oss2.Bucket(oss2.Auth(self.access_key_id, self.access_key_secret), self.endpoint, self.bucket_name)

    def save(self, name, filepath):
        full_url = "http://" + self.bucket_name + "." + self.endpoint + "/" + name
        if self.bucket.object_exists(name):
            self.bucket.delete_object(name)
        try:
            self.bucket.put_object_from_file(name, filepath)
        except Exception as e:
            raise

        return full_url


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import os

import tensorflow as tf
from tensorflow.python.keras.layers import InputLayer, Conv2D, Activation, MaxPooling2D, Dropout, Flatten, Dense
from tensorflow.python.keras.models import Sequential
from tensorflow.python.keras.optimizers import RMSprop
from tensorflow.python.saved_model.signature_constants import PREDICT_INPUTS

from environment import create_trainer_environment
from keras import optimizers
from keras.models import *
import keras.backend as K

from utils.resnet_helpers import *
if K.backend() == 'tensorflow':
    from utils.BilinearUpSampling import *
from utils.SegDataGenerator import *

HEIGHT = 224
WIDTH = 224
DEPTH = 3
NUM_CLASSES = 22
NUM_DATA_BATCHES = 5
NUM_EXAMPLES_PER_EPOCH_FOR_TRAIN = 10000 * NUM_DATA_BATCHES
BATCH_SIZE = 128

def keras_model_fn(hyperparameters):
    """keras_model_fn receives hyperparameters from the training job and returns a compiled keras model.
    The model will be transformed into a TensorFlow Estimator before training and it will be saved in a
    TensorFlow Serving SavedModel at the end of training.

    Args:
        hyperparameters: The hyperparameters passed to the SageMaker TrainingJob that runs your TensorFlow
                         training script.
    Returns: A compiled Keras model
    """
    # the trainer environment contains useful information about
    env = create_trainer_environment()
    print('creating SageMaker trainer environment:\n%s' % str(env))

    # getting the hyperparameters
    batch_size = env.hyperparameters.get('batch_size', object_type=int)
    data_augmentation = env.hyperparameters.get('data_augmentation', default=True, object_type=bool)
    learning_rate = env.hyperparameters.get('learning_rate', default=.0001, object_type=float)
    width_shift_range = env.hyperparameters.get('width_shift_range', object_type=float)
    height_shift_range = env.hyperparameters.get('height_shift_range', object_type=float)
    EPOCHS = env.hyperparameters.get('epochs', default=10, object_type=int)

    weight_decay = 0.
    batch_momentum = 0.9
    batch_shape = x_train.shape
    classes = 22
    img_input = Input(batch_shape=batch_shape)
    image_size = batch_shape[2:4]
    print('batch_shape' + str(batch_shape))
    print('image_size' + str(image_size))
    bn_axis = 1  # TODO(Shun): Check '3' is ok or not. Documentation recommends '1'

    x = Conv2D(64, (7, 7), strides=(2, 2), padding='same', name='conv1', kernel_regularizer=l2(weight_decay))(img_input)
    x = BatchNormalization(axis=bn_axis, name='bn_conv1', momentum=batch_momentum)(x)
    x = Activation('relu')(x)
    # x = MaxPooling2D((3, 3), strides=(2, 2))(x)
    x = MaxPooling2D((2, 2), strides=(2, 2))(x)  # TODO(Shun): (2, 2) is just random. Further consideration needed

    x = conv_block(3, [64, 64, 256], stage=2, block='a', weight_decay=weight_decay, strides=(1, 1), batch_momentum=batch_momentum)(x)
    x = identity_block(3, [64, 64, 256], stage=2, block='b', weight_decay=weight_decay, batch_momentum=batch_momentum)(x)
    x = identity_block(3, [64, 64, 256], stage=2, block='c', weight_decay=weight_decay, batch_momentum=batch_momentum)(x)

    x = conv_block(3, [128, 128, 512], stage=3, block='a', weight_decay=weight_decay, batch_momentum=batch_momentum)(x)
    x = identity_block(3, [128, 128, 512], stage=3, block='b', weight_decay=weight_decay, batch_momentum=batch_momentum)(x)
    x = identity_block(3, [128, 128, 512], stage=3, block='c', weight_decay=weight_decay, batch_momentum=batch_momentum)(x)
    x = identity_block(3, [128, 128, 512], stage=3, block='d', weight_decay=weight_decay, batch_momentum=batch_momentum)(x)

    x = conv_block(3, [256, 256, 1024], stage=4, block='a', weight_decay=weight_decay, batch_momentum=batch_momentum)(x)
    x = identity_block(3, [256, 256, 1024], stage=4, block='b', weight_decay=weight_decay, batch_momentum=batch_momentum)(x)
    x = identity_block(3, [256, 256, 1024], stage=4, block='c', weight_decay=weight_decay, batch_momentum=batch_momentum)(x)
    x = identity_block(3, [256, 256, 1024], stage=4, block='d', weight_decay=weight_decay, batch_momentum=batch_momentum)(x)
    x = identity_block(3, [256, 256, 1024], stage=4, block='e', weight_decay=weight_decay, batch_momentum=batch_momentum)(x)
    x = identity_block(3, [256, 256, 1024], stage=4, block='f', weight_decay=weight_decay, batch_momentum=batch_momentum)(x)

    x = atrous_conv_block(3, [512, 512, 2048], stage=5, block='a', weight_decay=weight_decay, atrous_rate=(2, 2), batch_momentum=batch_momentum)(x)
    x = atrous_identity_block(3, [512, 512, 2048], stage=5, block='b', weight_decay=weight_decay, atrous_rate=(2, 2), batch_momentum=batch_momentum)(x)
    x = atrous_identity_block(3, [512, 512, 2048], stage=5, block='c', weight_decay=weight_decay, atrous_rate=(2, 2), batch_momentum=batch_momentum)(x)
    # classifying layer
    # x = Conv2D(classes, (3, 3), dilation_rate=(2, 2), kernel_initializer='normal', activation='linear', padding='same', strides=(1, 1), kernel_regularizer=l2(weight_decay))(x)
    x = Conv2D(classes, (1, 1), kernel_initializer='he_normal', activation='linear', padding='same', strides=(1, 1), kernel_regularizer=l2(weight_decay))(x)

    # TODO(Warning): UpSampling2D of Keras cannot accurately represent BilinearUpSampling2D of Tensorflow
    if K.backend() == 'tensorflow':
        x = BilinearUpSampling2D(target_size=tuple(image_size))(x)
    elif K.backend() == 'mxnet':
        # TODO(Warning): This method works only when the input image size is 224 * 224
        x = UpSampling2D(size=(16, 16), data_format=None)(x)
        # x = K.symbol.UpSampling(x, (image_size[0], image_size[1]), sample_type='bilinear')
    # x = K.resize_images(x, image_size[0], image_size[1], 'channels_first')

    _model = Model(img_input, x)

    # initiate RMSprop optimizer
    opt = optimizers.rmsprop(lr=learning_rate, decay=1e-6)

    # Let's train the model using RMSprop
    _model.compile(loss='categorical_crossentropy', optimizer=opt, metrics=['accuracy'])

    return _model

def serving_input_fn(hyperparameters):
    """This function defines the placeholders that will be added to the model during serving.
    The function returns a tf.estimator.export.ServingInputReceiver object, which packages the
    placeholders and the resulting feature Tensors together.
    For more information: https://github.com/aws/sagemaker-python-sdk/blob/master/src/sagemaker/tensorflow/README.rst#creating-a-serving_input_fn

    Args:
        hyperparameters: The hyperparameters passed to SageMaker TrainingJob that runs your TensorFlow
                        training script.
    Returns: ServingInputReceiver or fn that returns a ServingInputReceiver
    """

    # Notice that the input placeholder has the same input shape as the Keras model input
    tensor = tf.placeholder(tf.float32, shape=[None, HEIGHT, WIDTH, DEPTH])

    # The inputs key PREDICT_INPUTS matches the Keras InputLayer name
    inputs = {PREDICT_INPUTS: tensor}
    return tf.estimator.export.ServingInputReceiver(inputs, inputs)

def train_input_fn(training_dir, hyperparameters):
    """Returns input function that would feed the model during training"""
    return _input(tf.estimator.ModeKeys.TRAIN,
                  batch_size=BATCH_SIZE, data_dir=training_dir)

def eval_input_fn(training_dir, hyperparameters):
    """Returns input function that would feed the model during evaluation"""
    return _input(tf.estimator.ModeKeys.EVAL,
                  batch_size=BATCH_SIZE, data_dir=training_dir)

def _input(mode, batch_size, data_dir):
    """Uses the tf.data input pipeline for CIFAR-10 dataset.
    Args:
        mode: Standard names for model modes (tf.estimators.ModeKeys).
        batch_size: The number of samples per batch of input requested.
    """
    dataset = _record_dataset(_filenames(mode, data_dir))

    # For training repeat forever.
    if mode == tf.estimator.ModeKeys.TRAIN:
        dataset = dataset.repeat()

    dataset = dataset.map(_dataset_parser)
    dataset.prefetch(2 * batch_size)

    # For training, preprocess the image and shuffle.
    if mode == tf.estimator.ModeKeys.TRAIN:
        dataset = dataset.map(_train_preprocess_fn)
        dataset.prefetch(2 * batch_size)

        # Ensure that the capacity is sufficiently large to provide good random
        # shuffling.
        buffer_size = int(NUM_EXAMPLES_PER_EPOCH_FOR_TRAIN * 0.4) + 3 * batch_size
        dataset = dataset.shuffle(buffer_size=buffer_size)

    # Subtract off the mean and divide by the variance of the pixels.
    dataset = dataset.map(
        lambda image, label: (tf.image.per_image_standardization(image), label))
    dataset.prefetch(2 * batch_size)

    # Batch results by up to batch_size, and then fetch the tuple from the
    # iterator.
    iterator = dataset.batch(batch_size).make_one_shot_iterator()
    images, labels = iterator.get_next()

    # We must use the default input tensor name PREDICT_INPUTS
    return {PREDICT_INPUTS: images}, labels

def _train_preprocess_fn(image, label):
    """Preprocess a single training image of layout [height, width, depth]."""
    # Resize the image to add four extra pixels on each side.
    image = tf.image.resize_image_with_crop_or_pad(image, HEIGHT + 8, WIDTH + 8)

    # Randomly crop a [HEIGHT, WIDTH] section of the image.
    image = tf.random_crop(image, [HEIGHT, WIDTH, DEPTH])

    # Randomly flip the image horizontally.
    image = tf.image.random_flip_left_right(image)

    return image, label

def _dataset_parser(value):
    """Parse a CIFAR-10 record from value."""
    # Every record consists of a label followed by the image, with a fixed number
    # of bytes for each.
    label_bytes = 1
    image_bytes = HEIGHT * WIDTH * DEPTH
    record_bytes = label_bytes + image_bytes

    # Convert from a string to a vector of uint8 that is record_bytes long.
    raw_record = tf.decode_raw(value, tf.uint8)

    # The first byte represents the label, which we convert from uint8 to int32.
    label = tf.cast(raw_record[0], tf.int32)

    # The remaining bytes after the label represent the image, which we reshape
    # from [depth * height * width] to [depth, height, width].
    depth_major = tf.reshape(raw_record[label_bytes:record_bytes],
                             [DEPTH, HEIGHT, WIDTH])

    # Convert from [depth, height, width] to [height, width, depth], and cast as
    # float32.
    image = tf.cast(tf.transpose(depth_major, [1, 2, 0]), tf.float32)

    return image, tf.one_hot(label, NUM_CLASSES)

def _record_dataset(filenames):
    """Returns an input pipeline Dataset from `filenames`."""
    record_bytes = HEIGHT * WIDTH * DEPTH + 1
    return tf.data.FixedLengthRecordDataset(filenames, record_bytes)

def _filenames(mode, data_dir):
    """Returns a list of filenames based on 'mode'."""
    data_dir = os.path.join(data_dir, 'FileLists')

    assert os.path.exists(data_dir), '"FileLists" directory does not exist.'

    if mode == tf.estimator.ModeKeys.TRAIN:
        return os.path.join(data_dir, 'train.txt')

    elif mode == tf.estimator.ModeKeys.EVAL:
        return os.path.join(data_dir, 'val.txt')
    else:
        raise ValueError('Invalid mode: %s' % mode)


from setuptools import setup, find_packages

with open('README.md') as f:
    readme = f.read()

setup(
    name='PythonUtilities',
    version='0.1.7',
    description='Python utility tools.',
    long_description=readme,
    long_description_content_type="text/markdown",

    author='Ricky Schools',
    author_email='ricky.schools@fsinvestments.com',
    url='https://github.com/rickyschoolsFS/PythonUtilities',
    license=license,
    packages=find_packages(exclude=('tests', 'docs')),
    classifiers=("Programming Language :: Python :: 3",
                 "Development Status :: 1 - Planning",
                 'Intended Audience :: Developers',
                 ),
    install_requires=[
        'pandas',
        'beautifulsoup4',
        'SQLAlchemy',
        'py_trello',
        'simple_salesforce',
        'selenium',
        'salesforce_bulk',
        'python_dateutil',
        'trello',
        'setuptools',
        'chromedriver',
        'tqdm',
        'SQLAlchemy_Utils'
    ],
    python_requires='>3.0, <4'
)


#coding:utf-8
import requests
import urllib3
from common.upload import UpLoad
import constant.site as SID
#禁用安全警告
urllib3.disable_warnings()

url1 = 'http://xcloud.dev.xcharger.net/service/api/site'
url2 = 'http://xcloud.dev.xcharger.net/service/api/device/setting/site'
class Screenconfiguration(UpLoad):
    def __init__(self,s):
        self.s = s
    def ScreenLogo(self,deviceType,LogoType,fileurl,filesize,siteId=SID.siteId):
        '''屏幕Logo，LogoType的取值为logo,company,customized，deviceType取值为C1,C1L,C2,C4,C6,C6S
        company代表C1，C1L，C2顶部logo，
        logo代表C1,C1L的开机logo
        customized代表C4,C6,C6S的顶部logo'''
        deviceSetting = {
            "id":siteId,
            "deviceSetting":{
                "contentUI":{
                    deviceType:{
                        LogoType:[
                            {
                                "fileUrl":fileurl,
                                "fileSize":filesize,
                                "type":"png"
                            }
                        ]
                    }
                }
            }
        }
        res = self.s.post(url1,json=deviceSetting,verify=False)
        return res
    def ScreenText(self,deviceType,textType,text,siteId=SID.siteId):
        '''屏幕文字，deviceType取值为C1,C1L,C2,C4,C6,C6S
        textType取值为welcome,scanHintDesc,scanHintTitle,customized,customizedBottom,customizedBottom
        welcome表示C1,C1L设备的界面文字
        scanHintTitle表示C2设备的扫码界面标题
        scanHintDesc表示C2设备的扫码界面文字
        customized表示C4,C6,C6S设备的顶部文字
        customizedBottom表示C4,C6S设备的欢迎文字标题和欢迎文字内容，也表示C6设备的底部文字，但是在给C4,C6S传值text时要是有\n隔开'''
        if deviceType == 'C1' or deviceType == 'C1L':
            deviceSetting = {
                "id":siteId,
                "deviceSetting":{
                    "contentUI":{
                        deviceType:{
                            textType:
                                [
                                    {
                                        "text":"欢迎使用\n%s\n请扫码充电"%text,
                                        "type":"text"
                                    }
                                ]
                        }
                    }
                }
            }
        else:
            deviceSetting = {
                "id": siteId,
                "deviceSetting": {
                    "contentUI": {
                        deviceType: {
                            textType:
                                [
                                    {
                                        "text":text,
                                        "type":"text"
                                    }
                                ]
                        }
                    }
                }
            }
        res = self.s.post(url1,json=deviceSetting,verify=False)
        return res
    def ADInfo(self,deviceType,ADType,fileurl,filesize,type,duration,siteId=SID.siteId):
        '''广告信息,ADType取值为wakeUpAdvsite，scanAdvsite，pullAdvsite，beforeCharging，welcome
        deviceType取值为C1,C1L,C2,C4,C6,C6S
        type的取值为png,jpg,peg和mp4
        wakeUpAdvsite表示C1,C1L,C2设备的唤醒后广告
        scanAdvsite表示C1,C1L,C2设备的扫码后广告
        pullAdvsite表示C1,C1L,C2设备的拔枪后广告
        beforeCharging表示C4,C6,C6S设备的扫码和拔枪后广告
        welcome表示C4,C6,C6S设备的唤醒时广告'''
        deviceSetting = {
            "id":siteId,
            "deviceSetting":{
                "contentAD":{
                    deviceType:{
                        ADType:
                            [
                                {
                                    "fileUrl":fileurl,
                                    "fileSize":filesize,
                                    "type":type,
                                    "duration":duration
                                }
                            ]
                    }
                }
            }
        }
        res = self.s.post(url1,json=deviceSetting,verify=False)
        return res
    def AD_afterChargering(self,deviceType,filelists,siteId=SID.siteId):
        '''C4,C6,C6S的空闲时广告，filelist参数类型为列表'''
        deviceSetting = {
            "id":siteId,
            "deviceSetting":{
                "contentAD":{
                    deviceType:{
                        "afterCharging":filelists
                    }
                }
            }
        }
        res = self.s.post(url1,json=deviceSetting,verify=False)
        return res
    def DeleteAd(self,deviceType,ADType,siteId=SID.siteId):
        '''删除广告,参数ADType取值为wakeUpAdvsite，scanAdvsite，pullAdvsite，beforeCharging，afterCharging，welcome
        deviceType取值为C1,C1L,C2,C4,C6,C6S
        wakeUpAdvsite表示C1,C1L,C2设备的唤醒后广告
        scanAdvsite表示C1,C1L,C2设备的扫码后广告
        pullAdvsite表示C1,C1L,C2设备的拔枪后广告
        beforeCharging表示C4,C6,C6S设备的扫码和拔枪后广告
        afterCharging表示C4,C6,C6S设备的空闲时广告
        welcome表示C4,C6,C6S设备的唤醒时广告'''
        deviceSetting = {
            "id":siteId,
            "deviceSetting":{
                "contentAD":{
                    deviceType:{
                        ADType:[]
                    }
                }
            }
        }
        res = self.s.post(url1,json=deviceSetting,verify=False)
        return res
    def PushSetting(self,deviceType,deviceIds,siteId=SID.siteId):
        '''推送配置,参数deviceIds是一个列表，deviceType取值为C1,C1L,C2,C4,C6,C6S'''
        if deviceType == 'C1' or deviceType == 'C1L':
            deviceSetting = {
                "siteId":siteId,
                "contentUI":{
                    deviceType:["logo","company","welcome"]
                },
                "contentAD":{
                    deviceType:["wakeUpAdvsite","scanAdvsite","pullAdvsite"]
                },
                "deviceIds":deviceIds  #当给传值deviceIds为空列表时，表示全部推送
            }
            res = self.s.post(url2,json=deviceSetting,verify=False)
        elif deviceType == 'C2':
            deviceSetting = {
                "siteId": siteId,
                "contentUI": {
                    deviceType: ["company", "scanHintDesc", "scanHintTitle"]
                },
                "contentAD": {
                    deviceType: ["wakeUpAdvsite", "scanAdvsite", "pullAdvsite"]
                },
                "deviceIds": deviceIds  # 当给传值deviceIds为空列表时，表示全部推送
            }
            res = self.s.post(url2, json=deviceSetting, verify=False)
        elif deviceType == 'C4' or deviceType == 'C6' or deviceType == 'C6S':
            deviceSetting = {
                "siteId": siteId,
                "contentUI": {
                    deviceType: ["customized", "customizedBottom"]
                },
                "contentAD": {
                    deviceType: ["welcome", "beforeCharging", "afterCharging"]
                },
                "deviceIds": deviceIds  # 当给传值deviceIds为空列表时，表示全部推送
            }
            res = self.s.post(url2, json=deviceSetting, verify=False)
        return res

if __name__ == '__main__':
    s = requests.session()
    Ad = Screenconfiguration(s)
    Ad.login('zhichong','xcharger88')
    C1fileurl, C1filesize = Ad.UpLoad('D:\Xcharger\图片\\audilogo1.png')
    print(C1fileurl)
    print(C1filesize)
    res = Ad.ScreenLogo('C1','logo',C1fileurl,C1filesize)
    print(res.json())


from glob import glob
import json
import os.path
import re

root = "/home/saurabh/Documents/Study_Matter/VLR_16824/project/json_test_crop"
out_dir = "/home/saurabh/Documents/Study_Matter/VLR_16824/project/data"

label_out = {}
for dir_path in glob(f"{root}/*"):
    dir_name = os.path.basename(dir_path)
    frame_data = {}
    for file_path in glob(f"{dir_path}/*.json"):
        out = {}
        max_idx = 0
        with open(file_path) as json_ptr:
            m = re.search(r".*?_(\d+)_(\d+)_keypoints\.json",os.path.basename(file_path))
            if not m:
                raise Exception("Regex should match")
            frame_0 = int(m.group(2))
            file_num = int(m.group(1))
            src = json.load(json_ptr)
            xys = src["people"][0]["pose_keypoints_2d"]
            xy = [p for i, p in enumerate(xys) if i % 3 != 2]
            s = [p for i, p in enumerate(xys) if i % 3 == 2]
            frame_data[frame_0+1] ={}
            cur_data = frame_data[frame_0+1]
            cur_data["frame_index"] = frame_0+1
            cur_data["skeleton"] = [{"pose": xy,
                                    "score": s}]
            if frame_0+1 > max_idx:
                max_idx = frame_0+1
        if file_num in range(2930,2945):
            label = "right"
            label_idx = 0
        elif file_num in range(2945, 2960):
            label = "left"
            label_idx = 1
        elif file_num in range(2960, 2975):
            label = "parallel"
            label_idx = 2
        else:
            raise Exception("File numbers should be between 2930-2974")
    out["data"] = []
    for idx in range(1, max_idx+1):
        out["data"].append(frame_data[idx])
    out["label"] = label
    out["label_index"] = label_idx
    label_out[dir_name] = {"has_skeleton" : True,
                           "label": label,
                           "label_idx": label_idx}

    with open(f"{out_dir}/train/{dir_name}.json", "w") as out_json:
        json.dump(out, out_json)

with open(f"{out_dir}/train_label.json", "w") as label_file:
    json.dump(label_out, label_file)


from . import build_response, build_speechlet_response, pos_to_int
from endpoints import Endpoints

def get_sendmoney_response(name, session, intent):
    '''
        This is the response when the user wants to send money
    '''
    # ensure session attributes are passed on throughout the session
    session_attributes = session['attributes']

    # load intent values
    try:
        dest = intent['slots']['dest']['value']
        amount = intent['slots']['amount']['value']
        input_number = intent['slots']['number']['value']
        if type(input_number) == str:
            number = pos_to_int(input_number)

        speech_output = f"Sending {dest} {amount} cents from the {input_number} account"
    except:
        speech_output = "There was an error."

    res = Endpoints.transaction_between_users(
            sourceOwner=name,
            destinationOwner=dest,
            sourceAccountNumber=number,
            amount=amount)
    print(res)
    if res == 'Error':
        raise ValueError

    card_title = "SendMoney"
    reprompt_text = speech_output
    should_end_session = False
    return build_response(session_attributes, build_speechlet_response(
        card_title, speech_output, reprompt_text, should_end_session))