"""
Middleware used for adjusting headers in a response before it is sent to the end user.
"""

from django.utils.deprecation import MiddlewareMixin
import six

class HeaderControlMiddleware(MiddlewareMixin):
    """
    Middleware that can modify/remove headers in a response.

    This can be used, for example, to remove headers i.e. drop any Vary headers to improve cache performance.
    """

    def process_response(self, _request, response):
        """
        Processes the given response, potentially remove or modifying headers.
        """

        for header in getattr(response, 'remove_headers', []):
            del response[header]

        for header, value in six.iteritems(getattr(response, 'force_headers', {})):
            response[header] = value

        ret


        for header in getattr(response, 'remove_headers', []):
            del response[header]

        for header, value in six.iteritems(getattr(response, 'force_headers', {})):
            response[header] = value

        return response

"""
Middleware used for adjusting headers in a response before it is sent to the end user.
"""

from django.utils.deprecation import MiddlewareMixin
import six

class HeaderControlMiddleware(MiddlewareMixin):
    """
    Middleware that can modify/remove headers in a response.

    This can be used, for example, to remove headers i.e. drop any Vary headers to improve cache performance.
    """

    def process_response(self, _request, response):
        """
        Processes the given response, potentially remove or modifying headers.
        """


for header, value in six.iteritems(getattr(response, 'force_headers', {})):
            response[header] = value

"""
Middleware used for adjusting headers in a response before it is sent to the end user.
"""

from django.utils.deprecation import MiddlewareMixin
import six

class HeaderControlMiddleware(MiddlewareMixin):
    """
    Middleware that can modify/remove headers in a response.

    This can be used, for example, to remove headers i.e. drop any Vary headers to improve cache performance.
    """

    def process_response(self, _request, response):
        """
        Processes the given response, potentially remove or modifying headers.
        """

        for header in getattr(response, 'remove_headers', []):
            del response[header]


"""AUCR main auth plugin api features."""
from flask import jsonify, request, url_for
from aucr_app import db
from aucr_app.plugins.auth.models import User
from aucr_app.plugins.api.routes import api_page
from aucr_app.plugins.api.auth import token_auth
from aucr_app.plugins.errors.api.errors import bad_request

@api_page.route('/users/<int:id>', methods=['GET'])
@token_auth.login_required
def get_user(id):
    """Return User id from database."""
    return jsonify(User.query.get_or_404(id).to_dict())

@api_page.route('/users', methods=['GET'])
@token_auth.login_required
def get_users():
    """Return user list."""
    page = request.args.get('page', 1, type=int)
    per_page = min(request.args.get('per_page', 10, type=int), 100)
    data = User.to_collection_dict(User.query, page, per_page, 'api.get_users')
    return jsonify(data)

@api_page.route('/users', methods=['POST'])
def create_user():
    """API Create new user."""
    data = request.get_json() or {}
    if 'username' not in data or 'email' not in data or 'password' not in data:
        return bad_request('must include username, email and password fields')
    new_user = data['username']
    current_user = User.query.filter_by(username=new_user).first()
    new_email = data['email']
    current_email = User.query.filter_by(email=new_email).first()
    if current_user:
        return bad_request('please use a different username')
    if current_email:
        return bad_request('please use a different email address')
    user = User(username=new_user, email=new_email)
    user.set_password(data['password'])
    db.session.add(user)
    db.session.commit()

    user.from_dict(data, new_user=True)
    response = jsonify(user.to_dict())
    response.status_code = 201
    return response

@api_page.route('/users/<int:id_>', methods=['PUT'])
@token_auth.login_required

"""API Update user account."""
    user = User.query.get_or_404(id_)
    data = request.get_json() or {}
    if 'username' in data and data['username'] != user.username and \
            User.query.filter_by(username=data['username']).first():
        return bad_request('please use a different username')
    if 'email' in data and data['email'] != user.email and User.query.filter_by(email=data['email']).first():
        return bad_request('please use a different email address')
    user.from_dict(data, new_user=False)
    db.session.commit()
    return jsonify(user.to_dict())


"""Return user list."""
    page = request.args.get('page', 1, type=int)
    per_page = min(request.args.get('per_page', 10, type=int), 100)
    data = User.to_collection_dict(User.query, page, per_page, 'api.get_users')
    return jsonify(data)

"""AUCR main auth plugin api features."""
from flask import jsonify, request, url_for
from aucr_app import db
from aucr_app.plugins.auth.models import User
from aucr_app.plugins.api.routes import api_page
from aucr_app.plugins.api.auth import token_auth
from aucr_app.plugins.errors.api.errors import bad_request

@api_page.route('/users/<int:id>', methods=['GET'])
@token_auth.login_required
def get_user(id):
    """Return User id from database."""
    return jsonify(User.query.get_or_404(id).to_dict())

@api_page.route('/users', methods=['GET'])
@token_auth.login_required
def get_users():

@api_page.route('/users', methods=['POST'])
def create_user():
    """API Create new user."""
    data = request.get_json() or {}
    if 'username' not in data or 'email' not in data or 'password' not in data:
        return bad_request('must include username, email and password fields')
    new_user = data['username']
    current_user = User.query.filter_by(username=new_user).first()
    new_email = data['email']
    current_email = User.query.filter_by(email=new_email).first()
    if current_user:
        return bad_request('please use a different username')
    if current_email:
        return bad_request('please use a different email address')
    user = User(username=new_user, email=new_email)
    user.set_password(data['password'])
    db.session.add(user)
    db.session.commit()

    user.from_dict(data, new_user=True)
    response = jsonify(user.to_dict())
    response.status_code = 201
    return response

@api_page.route('/users/<int:id_>', methods=['PUT'])
@token_auth.login_required
def update_user(id_):
    """API Update user account."""
    user = User.query.get_or_404(id_)
    data = request.get_json() or {}
    if 'username' in data and data['username'] != user.username and \
            User.query.filter_by(username=data['username']).first():
        return bad_request('please use a different username')
    if 'email' in data and data['email'] != user.email and User.query.filter_by(email=data['email']).first():
        return bad_request('please use a different email address')
    user.from_dict(data, new_user=False)
    db.session.commit()
    return jsonify(user.to_dict())


"""API Create new user."""
    data = request.get_json() or {}
    if 'username' not in data or 'email' not in data or 'password' not in data:
        return bad_request('must include username, email and password fields')
    new_user = data['username']
    current_user = User.query.filter_by(username=new_user).first()
    new_email = data['email']

"""AUCR main auth plugin api features."""
from flask import jsonify, request, url_for
from aucr_app import db
from aucr_app.plugins.auth.models import User
from aucr_app.plugins.api.routes import api_page
from aucr_app.plugins.api.auth import token_auth
from aucr_app.plugins.errors.api.errors import bad_request

@api_page.route('/users/<int:id>', methods=['GET'])
@token_auth.login_required
def get_user(id):
    """Return User id from database."""
    return jsonify(User.query.get_or_404(id).to_dict())

@api_page.route('/users', methods=['GET'])
@token_auth.login_required
def get_users():
    """Return user list."""
    page = request.args.get('page', 1, type=int)
    per_page = min(request.args.get('per_page', 10, type=int), 100)
    data = User.to_collection_dict(User.query, page, per_page, 'api.get_users')
    return jsonify(data)

@api_page.route('/users', methods=['POST'])
def create_user():

    current_email = User.query.filter_by(email=new_email).first()
    if current_user:
        return bad_request('please use a different username')
    if current_email:
        return bad_request('please use a different email address')
    user = User(username=new_user, email=new_email)
    user.set_password(data['password'])
    db.session.add(user)
    db.session.commit()

    user.from_dict(data, new_user=True)
    response = jsonify(user.to_dict())
    response.status_code = 201
    return response

@api_page.route('/users/<int:id_>', methods=['PUT'])
@token_auth.login_required
def update_user(id_):
    """API Update user account."""
    user = User.query.get_or_404(id_)
    data = request.get_json() or {}
    if 'username' in data and data['username'] != user.username and \
            User.query.filter_by(username=data['username']).first():
        return bad_request('please use a different username')
    if 'email' in data and data['email'] != user.email and User.query.filter_by(email=data['email']).first():
        return bad_request('please use a different email address')
    user.from_dict(data, new_user=False)
    db.session.commit()
    return jsonify(user.to_dict())


current_email = User.query.filter_by(email=new_email).first()
    if current_user:
        return bad_request('please use a different username')
    if current_email:
        return bad_request('please use a different email address')
    user = User(username=new_user, email=new_email)
    user.set_password(data['password'])

"""AUCR main auth plugin api features."""
from flask import jsonify, request, url_for
from aucr_app import db
from aucr_app.plugins.auth.models import User
from aucr_app.plugins.api.routes import api_page
from aucr_app.plugins.api.auth import token_auth
from aucr_app.plugins.errors.api.errors import bad_request

@api_page.route('/users/<int:id>', methods=['GET'])
@token_auth.login_required
def get_user(id):
    """Return User id from database."""
    return jsonify(User.query.get_or_404(id).to_dict())

@api_page.route('/users', methods=['GET'])
@token_auth.login_required
def get_users():
    """Return user list."""
    page = request.args.get('page', 1, type=int)
    per_page = min(request.args.get('per_page', 10, type=int), 100)
    data = User.to_collection_dict(User.query, page, per_page, 'api.get_users')
    return jsonify(data)

@api_page.route('/users', methods=['POST'])
def create_user():
    """API Create new user."""
    data = request.get_json() or {}
    if 'username' not in data or 'email' not in data or 'password' not in data:
        return bad_request('must include username, email and password fields')
    new_user = data['username']
    current_user = User.query.filter_by(username=new_user).first()
    new_email = data['email']

    db.session.add(user)
    db.session.commit()

    user.from_dict(data, new_user=True)
    response = jsonify(user.to_dict())
    response.status_code = 201
    return response

@api_page.route('/users/<int:id_>', methods=['PUT'])
@token_auth.login_required
def update_user(id_):
    """API Update user account."""
    user = User.query.get_or_404(id_)
    data = request.get_json() or {}
    if 'username' in data and data['username'] != user.username and \
            User.query.filter_by(username=data['username']).first():
        return bad_request('please use a different username')
    if 'email' in data and data['email'] != user.email and User.query.filter_by(email=data['email']).first():
        return bad_request('please use a different email address')
    user.from_dict(data, new_user=False)
    db.session.commit()
    return jsonify(user.to_dict())


db.session.add(user)
    db.session.commit()

    user.from_dict(data, new_user=True)
    response = jsonify(user.to_dict())
    response.status_code = 201
    return response

"""AUCR main auth plugin api features."""
from flask import jsonify, request, url_for
from aucr_app import db
from aucr_app.plugins.auth.models import User
from aucr_app.plugins.api.routes import api_page
from aucr_app.plugins.api.auth import token_auth
from aucr_app.plugins.errors.api.errors import bad_request

@api_page.route('/users/<int:id>', methods=['GET'])
@token_auth.login_required
def get_user(id):
    """Return User id from database."""
    return jsonify(User.query.get_or_404(id).to_dict())

@api_page.route('/users', methods=['GET'])
@token_auth.login_required
def get_users():
    """Return user list."""
    page = request.args.get('page', 1, type=int)
    per_page = min(request.args.get('per_page', 10, type=int), 100)
    data = User.to_collection_dict(User.query, page, per_page, 'api.get_users')
    return jsonify(data)

@api_page.route('/users', methods=['POST'])
def create_user():
    """API Create new user."""
    data = request.get_json() or {}
    if 'username' not in data or 'email' not in data or 'password' not in data:
        return bad_request('must include username, email and password fields')
    new_user = data['username']
    current_user = User.query.filter_by(username=new_user).first()
    new_email = data['email']
    current_email = User.query.filter_by(email=new_email).first()
    if current_user:
        return bad_request('please use a different username')
    if current_email:
        return bad_request('please use a different email address')
    user = User(username=new_user, email=new_email)
    user.set_password(data['password'])

@api_page.route('/users/<int:id_>', methods=['PUT'])
@token_auth.login_required
def update_user(id_):
    """API Update user account."""
    user = User.query.get_or_404(id_)
    data = request.get_json() or {}
    if 'username' in data and data['username'] != user.username and \
            User.query.filter_by(username=data['username']).first():
        return bad_request('please use a different username')
    if 'email' in data and data['email'] != user.email and User.query.filter_by(email=data['email']).first():
        return bad_request('please use a different email address')
    user.from_dict(data, new_user=False)
    db.session.commit()
    return jsonify(user.to_dict())


"""AUCR main auth plugin api features."""
from flask import jsonify, request, url_for
from aucr_app import db
from aucr_app.plugins.auth.models import User
from aucr_app.plugins.api.routes import api_page
from aucr_app.plugins.api.auth import token_auth
from aucr_app.plugins.errors.api.errors import bad_request

@api_page.route('/users/<int:id>', methods=['GET'])
@token_auth.login_required
def get_user(id):
    """Return User id from database."""
    return jsonify(User.query.get_or_

@api_page.route('/users', methods=['GET'])
@token_auth.login_required
def get_users():
    """Return user list."""
    page = request.args.get('page', 1, type=int)
    per_page = min(request.args.get('per_page', 10, type=int), 100)
    data = User.to_collection_dict(User.query, page, per_page, 'api.get_users')
    return jsonify(data)

@api_page.route('/users', methods=['POST'])
def create_user():
    """API Create new user."""
    data = request.get_json() or {}
    if 'username' not in data or 'email' not in data or 'password' not in data:
        return bad_request('must include username, email and password fields')
    new_user = data['username']
    current_user = User.query.filter_by(username=new_user).first()
    new_email = data['email']
    current_email = User.query.filter_by(email=new_email).first()
    if current_user:
        return bad_request('please use a different username')
    if current_email:
        return bad_request('please use a different email address')
    user = User(username=new_user, email=new_email)
    user.set_password(data['password'])
    db.session.add(user)
    db.session.commit()

    user.from_dict(data, new_user=True)
    response = jsonify(user.to_dict())
    response.status_code = 201
    return response

@api_page.route('/users/<int:id_>', methods=['PUT'])
@token_auth.login_required
def update_user(id_):
    """API Update user account."""
    user = User.query.get_or_404(id_)
    data = request.get_json() or {}
    if 'username' in data and data['username'] != user.username and \
            User.query.filter_by(username=data['username']).first():
        return bad_request('please use a different username')
    if 'email' in data and data['email'] != user.email and User.query.filter_by(email=data['email']).first():
        return bad_request('please use a different email address')
    user.from_dict(data, new_user=False)
    db.session.commit()
    return jsonify(user.to_dict())


    page = request.args.get('page', 1, type=int)
    per_page = min(request.args.get('per_page', 10, type=int), 100)
    data = User.to_collection_dict(User.query, page, per_page, 'api.get_users')
    return jsonify(data)

"""AUCR main auth plugin api features."""
from flask import jsonify, request, url_for
from aucr_app import db
from aucr_app.plugins.auth.models import User
from aucr_app.plugins.api.routes import api_page
from aucr_app.plugins.api.auth import token_auth
from aucr_app.plugins.errors.api.errors import bad_request

@api_page.route('/users/<int:id>', methods=['GET'])
@token_auth.login_required
def get_user(id):
    """Return User id from database."""
    return jsonify(User.query.get_or_404(id).to_dict())

@api_page.route('/users', methods=['GET'])
@token_auth.login_required
def get_users():
    """Return user list."""


if current_email:
        return bad_request('please use a different email address')

"""AUCR main auth plugin api features."""
from flask import jsonify, request, url_for
from aucr_app import db
from aucr_app.plugins.auth.models import User
from aucr_app.plugins.api.routes import api_page
from aucr_app.plugins.api.auth import token_auth
from aucr_app.plugins.errors.api.errors import bad_request

@api_page.route('/users/<int:id>', methods=['GET'])
@token_auth.login_required
def get_user(id):
    """Return User id from database."""
    return jsonify(User.query.get_or_404(id).to_dict())

@api_page.route('/users', methods=['GET'])
@token_auth.login_required
def get_users():
    """Return user list."""
    page = request.args.get('page', 1, type=int)
    per_page = min(request.args.get('per_page', 10, type=int), 100)
    data = User.to_collection_dict(User.query, page, per_page, 'api.get_users')
    return jsonify(data)

@api_page.route('/users', methods=['POST'])
def create_user():
    """API Create new user."""
    data = request.get_json() or {}
    if 'username' not in data or 'email' not in data or 'password' not in data:
        return bad_request('must include username, email and password fields')
    new_user = data['username']
    current_user = User.query.filter_by(username=new_user).first()
    new_email = data['email']
    current_email = User.query.filter_by(email=new_email).first()
    if current_user:
        return bad_request('please use a different username')

    user = User(username=new_user, email=new_email)
    user.set_password(data['password'])
    db.session.add(user)
    db.session.commit()

    user.from_dict(data, new_user=True)
    response = jsonify(user.to_dict())
    response.status_code = 201
    return response

@api_page.route('/users/<int:id_>', methods=['PUT'])
@token_auth.login_required
def update_user(id_):
    """API Update user account."""
    user = User.query.get_or_404(id_)
    data = request.get_json() or {}
    if 'username' in data and data['username'] != user.username and \
            User.query.filter_by(username=data['username']).first():
        return bad_request('please use a different username')
    if 'email' in data and data['email'] != user.email and User.query.filter_by(email=data['email']).first():
        return bad_request('please use a different email address')
    user.from_dict(data, new_user=False)
    db.session.commit()
    return jsonify(user.to_dict())


def getNetworkColor(cls, network, nodeByID):

import bpy
from .. tree_info import getNetworks
from .. utils.layout import writeText
from .. preferences import getColorSettings

class NetworkColorsMode:
    @classmethod
    def colorNetwork(cls, network, nodesInNetwork, nodeByID = None):
        networkColor = cls.getNetworkColor(network, nodeByID)
        for node in nodesInNetwork:
            if not node.useNetworkColor: continue
            node.use_custom_color = True
            color = networkColor
            if node.bl_idname == "an_InvokeSubprogramNode":
                if node.subprogramNetwork: color = cls.getNetworkColor(node.subprogramNetwork, nodeByID)
            node.color = color

    @classmethod

colors = getColorSettings()
        if network.type == "Invalid": return colors.invalidNetwork
        if network.type == "Main": return colors.mainNetwork
        if network.type in ("Group", "Loop", "Script"):
            return network.getOwnerNode(nodeByID).networkColor

class NeededCopiesMode:
    @classmethod
    def colorNetwork(cls, network, nodesInNetwork, nodeByID = None):
        for node in nodesInNetwork:
            node.use_custom_color = True

            neededCopies = sum(socket.execution.neededCopies for socket in node.outputs)
            if neededCopies == 0:
                color = (0.7, 0.9, 0.7)
            else:
                color = (1.0, 0.3, 0.3)
            node.color = color

def colorAllNodes():
    for network in getNetworks():
        colorNetwork(network, network.getAnimationNodes())

def colorNetworks(nodesByNetworkDict, nodeByID = None):
    for network, nodes in nodesByNetworkDict.items():
        colorNetwork(network, nodes, nodeByID)

def colorNetwork(network, nodesInNetwork, nodeByID = None):
    mode = getColorSettings().nodeColorMode
    if mode == "NETWORKS":
        NetworkColorsMode.colorNetwork(network, nodesInNetwork)
    elif mode == "NEEDED_COPIES":
        NeededCopiesMode.colorNetwork(network, nodesInNetwork)

def drawNodeColorPanel(self, context):
    node = bpy.context.active_node
    if not getattr(node, "isAnimationNode", False): return

    col = self.layout.column(align = True)
    col.prop(node, "useNetworkColor")

    if node.bl_idname == "an_InvokeSubprogramNode": network = node.subprogramNetwork
    else: network = node.network

    if getattr(network, "isSubnetwork", False): col.prop(network.getOwnerNode(), "networkColor", text = "")
    else: writeText(col, "Only subprograms have a custom network color", width = 25)

# Register

def register():
    bpy.types.NODE_PT_active_node_color.append(drawNodeColorPanel)

def unregister():
    bpy.types.NODE_PT_active_node_color.remove(drawNodeColorPanel)


for node in nodesInNetwork:
            node.use_custom_color = True

            neededCopies = sum(socket.execution.neededCopies for socket in node.outputs)
            if neededCopies == 0:
                color = (0.7, 0.9, 0.7)
            else:
                color = (1.0, 0.3, 0.3)
            node.color = color

import bpy
from .. tree_info import getNetworks
from .. utils.layout import writeText
from .. preferences import getColorSettings

class NetworkColorsMode:
    @classmethod
    def colorNetwork(cls, network, nodesInNetwork, nodeByID = None):
        networkColor = cls.getNetworkColor(network, nodeByID)
        for node in nodesInNetwork:
            if not node.useNetworkColor: continue
            node.use_custom_color = True
            color = networkColor
            if node.bl_idname == "an_InvokeSubprogramNode":
                if node.subprogramNetwork: color = cls.getNetworkColor(node.subprogramNetwork, nodeByID)
            node.color = color

    @classmethod
    def getNetworkColor(cls, network, nodeByID):
        colors = getColorSettings()
        if network.type == "Invalid": return colors.invalidNetwork
        if network.type == "Main": return colors.mainNetwork
        if network.type in ("Group", "Loop", "Script"):
            return network.getOwnerNode(nodeByID).networkColor

class NeededCopiesMode:
    @classmethod
    def colorNetwork(cls, network, nodesInNetwork, nodeByID = None):

def colorAllNodes():
    for network in getNetworks():
        colorNetwork(network, network.getAnimationNodes())

def colorNetworks(nodesByNetworkDict, nodeByID = None):
    for network, nodes in nodesByNetworkDict.items():
        colorNetwork(network, nodes, nodeByID)

def colorNetwork(network, nodesInNetwork, nodeByID = None):
    mode = getColorSettings().nodeColorMode
    if mode == "NETWORKS":
        NetworkColorsMode.colorNetwork(network, nodesInNetwork)
    elif mode == "NEEDED_COPIES":
        NeededCopiesMode.colorNetwork(network, nodesInNetwork)

def drawNodeColorPanel(self, context):
    node = bpy.context.active_node
    if not getattr(node, "isAnimationNode", False): return

    col = self.layout.column(align = True)
    col.prop(node, "useNetworkColor")

    if node.bl_idname == "an_InvokeSubprogramNode": network = node.subprogramNetwork
    else: network = node.network

    if getattr(network, "isSubnetwork", False): col.prop(network.getOwnerNode(), "networkColor", text = "")
    else: writeText(col, "Only subprograms have a custom network color", width = 25)

# Register

def register():
    bpy.types.NODE_PT_active_node_color.append(drawNodeColorPanel)

def unregister():
    bpy.types.NODE_PT_active_node_color.remove(drawNodeColorPanel)


node = bpy.context.active_node
    if not getattr(node, "isAnimationNode", False): return

import bpy
from .. tree_info import getNetworks
from .. utils.layout import writeText
from .. preferences import getColorSettings

class NetworkColorsMode:
    @classmethod
    def colorNetwork(cls, network, nodesInNetwork, nodeByID = None):
        networkColor = cls.getNetworkColor(network, nodeByID)
        for node in nodesInNetwork:
            if not node.useNetworkColor: continue
            node.use_custom_color = True
            color = networkColor
            if node.bl_idname == "an_InvokeSubprogramNode":
                if node.subprogramNetwork: color = cls.getNetworkColor(node.subprogramNetwork, nodeByID)
            node.color = color

    @classmethod
    def getNetworkColor(cls, network, nodeByID):
        colors = getColorSettings()
        if network.type == "Invalid": return colors.invalidNetwork
        if network.type == "Main": return colors.mainNetwork
        if network.type in ("Group", "Loop", "Script"):
            return network.getOwnerNode(nodeByID).networkColor

class NeededCopiesMode:
    @classmethod
    def colorNetwork(cls, network, nodesInNetwork, nodeByID = None):
        for node in nodesInNetwork:
            node.use_custom_color = True

            neededCopies = sum(socket.execution.neededCopies for socket in node.outputs)
            if neededCopies == 0:
                color = (0.7, 0.9, 0.7)
            else:
                color = (1.0, 0.3, 0.3)
            node.color = color

def colorAllNodes():
    for network in getNetworks():
        colorNetwork(network, network.getAnimationNodes())

def colorNetworks(nodesByNetworkDict, nodeByID = None):
    for network, nodes in nodesByNetworkDict.items():
        colorNetwork(network, nodes, nodeByID)

def colorNetwork(network, nodesInNetwork, nodeByID = None):
    mode = getColorSettings().nodeColorMode
    if mode == "NETWORKS":
        NetworkColorsMode.colorNetwork(network, nodesInNetwork)
    elif mode == "NEEDED_COPIES":
        NeededCopiesMode.colorNetwork(network, nodesInNetwork)

def drawNodeColorPanel(self, context):

    col = self.layout.column(align = True)
    col.prop(node, "useNetworkColor")

    if node.bl_idname == "an_InvokeSubprogramNode": network = node.subprogramNetwork
    else: network = node.network

    if getattr(network, "isSubnetwork", False): col.prop(network.getOwnerNode(), "networkColor", text = "")
    else: writeText(col, "Only subprograms have a custom network color", width = 25)

# Register

def register():
    bpy.types.NODE_PT_active_node_color.append(drawNodeColorPanel)

def unregister():
    bpy.types.NODE_PT_active_node_color.remove(drawNodeColorPanel)


col = self.layout.column(align = True)
    col.prop(node, "useNetworkColor")

import bpy
from .. tree_info import getNetworks
from .. utils.layout import writeText
from .. preferences import getColorSettings

class NetworkColorsMode:
    @classmethod
    def colorNetwork(cls, network, nodesInNetwork, nodeByID = None):
        networkColor = cls.getNetworkColor(network, nodeByID)
        for node in nodesInNetwork:
            if not node.useNetworkColor: continue
            node.use_custom_color = True
            color = networkColor
            if node.bl_idname == "an_InvokeSubprogramNode":
                if node.subprogramNetwork: color = cls.getNetworkColor(node.subprogramNetwork, nodeByID)
            node.color = color

    @classmethod
    def getNetworkColor(cls, network, nodeByID):
        colors = getColorSettings()
        if network.type == "Invalid": return colors.invalidNetwork
        if network.type == "Main": return colors.mainNetwork
        if network.type in ("Group", "Loop", "Script"):
            return network.getOwnerNode(nodeByID).networkColor

class NeededCopiesMode:
    @classmethod
    def colorNetwork(cls, network, nodesInNetwork, nodeByID = None):
        for node in nodesInNetwork:
            node.use_custom_color = True

            neededCopies = sum(socket.execution.neededCopies for socket in node.outputs)
            if neededCopies == 0:
                color = (0.7, 0.9, 0.7)
            else:
                color = (1.0, 0.3, 0.3)
            node.color = color

def colorAllNodes():
    for network in getNetworks():
        colorNetwork(network, network.getAnimationNodes())

def colorNetworks(nodesByNetworkDict, nodeByID = None):
    for network, nodes in nodesByNetworkDict.items():
        colorNetwork(network, nodes, nodeByID)

def colorNetwork(network, nodesInNetwork, nodeByID = None):
    mode = getColorSettings().nodeColorMode
    if mode == "NETWORKS":
        NetworkColorsMode.colorNetwork(network, nodesInNetwork)
    elif mode == "NEEDED_COPIES":
        NeededCopiesMode.colorNetwork(network, nodesInNetwork)

def drawNodeColorPanel(self, context):
    node = bpy.context.active_node
    if not getattr(node, "isAnimationNode", False): return

    if node.bl_idname == "an_InvokeSubprogramNode": network = node.subprogramNetwork
    else: network = node.network

    if getattr(network, "isSubnetwork", False): col.prop(network.getOwnerNode(), "networkColor", text = "")
    else: writeText(col, "Only subprograms have a custom network color", width = 25)

# Register

def register():
    bpy.types.NODE_PT_active_node_color.append(drawNodeColorPanel)

def unregister():
    bpy.types.NODE_PT_active_node_color.remove(drawNodeColorPanel)


if node.bl_idname == "an_InvokeSubprogramNode": network = node.subprogramNetwork
    else: network = node.network

    if getattr(network, "isSubnetwork", False): col.prop(network.getOwnerNode(), "networkColor", text = "")
    else: writeText(col, "Only subprograms have a custom network color", width = 25)

import bpy
from .. tree_info import getNetworks
from .. utils.layout import writeText
from .. preferences import getColorSettings

class NetworkColorsMode:
    @classmethod
    def colorNetwork(cls, network, nodesInNetwork, nodeByID = None):
        networkColor = cls.getNetworkColor(network, nodeByID)
        for node in nodesInNetwork:
            if not node.useNetworkColor: continue
            node.use_custom_color = True
            color = networkColor
            if node.bl_idname == "an_InvokeSubprogramNode":
                if node.subprogramNetwork: color = cls.getNetworkColor(node.subprogramNetwork, nodeByID)
            node.color = color

    @classmethod
    def getNetworkColor(cls, network, nodeByID):
        colors = getColorSettings()
        if network.type == "Invalid": return colors.invalidNetwork
        if network.type == "Main": return colors.mainNetwork
        if network.type in ("Group", "Loop", "Script"):
            return network.getOwnerNode(nodeByID).networkColor

class NeededCopiesMode:
    @classmethod
    def colorNetwork(cls, network, nodesInNetwork, nodeByID = None):
        for node in nodesInNetwork:
            node.use_custom_color = True

            neededCopies = sum(socket.execution.neededCopies for socket in node.outputs)
            if neededCopies == 0:
                color = (0.7, 0.9, 0.7)
            else:
                color = (1.0, 0.3, 0.3)
            node.color = color

def colorAllNodes():
    for network in getNetworks():
        colorNetwork(network, network.getAnimationNodes())

def colorNetworks(nodesByNetworkDict, nodeByID = None):
    for network, nodes in nodesByNetworkDict.items():
        colorNetwork(network, nodes, nodeByID)

def colorNetwork(network, nodesInNetwork, nodeByID = None):
    mode = getColorSettings().nodeColorMode
    if mode == "NETWORKS":
        NetworkColorsMode.colorNetwork(network, nodesInNetwork)
    elif mode == "NEEDED_COPIES":
        NeededCopiesMode.colorNetwork(network, nodesInNetwork)

def drawNodeColorPanel(self, context):
    node = bpy.context.active_node
    if not getattr(node, "isAnimationNode", False): return

    col = self.layout.column(align = True)
    col.prop(node, "useNetworkColor")

# Register

def register():
    bpy.types.NODE_PT_active_node_color.append(drawNodeColorPanel)

def unregister():
    bpy.types.NODE_PT_active_node_color.remove(drawNodeColorPanel)


import bpy
from .. tree_info import getNetworks
from .. utils.layout import writeText
from .. preferences import getColorSettings

class NetworkColorsMode:
    @classmethod
    def colorNetwork(cls, network, nodesInNetwork, nodeByID = None):
        networkColor = cls.getNetworkColor(network, nodeByID)
        for node in nodesInNetwork:
            if not node.useNetworkColor: continue
            node.use_custom_color = True
            color = networkColor
            if node.bl_idname == "an_InvokeSubprogramNode":
                if node.subprogramNetwork: color = cls.getNetworkColor(node.subprogramNetwork, nodeByID)
            node.color = color

    @classmethod
    def getNetworkColor(cls, network, nodeByID):
        colors = getColorSettings()
        if network.type == "Invalid": return colors.invalidNetwork
        if network.type == "Main": return colors.mainNetwork
        if network.type in ("Group", "Loop", "Script"):
            return network.getOwnerNode(nodeByID).networkColor

class NeededCopiesMode:
    @classmethod
    def colorNetwork(cls, network, nodesInNetwork, nodeByID = None):
        for node in nodesInNetwork:
            node.use_custom_color = True

            neededCopies = sum(socket.execution.neededCopies for socket in node.outputs)
            if neededCopies == 0:
                color = (0.7, 0.9, 0.7)
            else:
                color = (1.0, 0.3, 0.3)
            node.color = color

def colorAllNodes():
    for network in getNetworks():
        colorNetwork(network, network.getAnimationNodes())

def colorNetworks(nodesByNetworkDict, nodeByID = None):
    for network, nodes in nodesByNetworkDict.items():
        colorNetwork(network, nodes, nodeByID)

def colorNetwork(network, nodesInNetwork, nodeByID = None):
    mode = getColorSettings().nodeColorMode
    if mode == "NETWORKS":
        NetworkColorsMode.colorNetwork(network, nodesInNetwork)
    elif mode == "NEEDED_COPIES":
        NeededCopiesMode.colorNetwork(network, nodesInNetwork)

def drawNodeColorPanel(self, context):
    node = bpy.context.a

    if not getattr(node, "isAnimationNode", False): return

    col = self.layout.column(align = True)
    col.prop(node, "useNetworkColor")

    if node.bl_idname == "an_InvokeSubprogramNode": network = node.subprogramNetwork
    else: network = node.network

    if getattr(network, "isSubnetwork", False): col.prop(network.getOwnerNode(), "networkColor", text = "")
    else: writeText(col, "Only subprograms have a custom network color", width = 25)

# Register

def register():
    bpy.types.NODE_PT_active_node_color.append(drawNodeColorPanel)

def unregister():
    bpy.types.NODE_PT_active_node_color.remove(drawNodeColorPanel)


if not getattr(node, "isAnimationNode", False): return

import bpy
from .. tree_info import getNetworks
from .. utils.layout import writeText
from .. preferences import getColorSettings

class NetworkColorsMode:
    @classmethod
    def colorNetwork(cls, network, nodesInNetwork, nodeByID = None):
        networkColor = cls.getNetworkColor(network, nodeByID)
        for node in nodesInNetwork:
            if not node.useNetworkColor: continue
            node.use_custom_color = True
            color = networkColor
            if node.bl_idname == "an_InvokeSubprogramNode":
                if node.subprogramNetwork: color = cls.getNetworkColor(node.subprogramNetwork, nodeByID)
            node.color = color

    @classmethod
    def getNetworkColor(cls, network, nodeByID):
        colors = getColorSettings()
        if network.type == "Invalid": return colors.invalidNetwork
        if network.type == "Main": return colors.mainNetwork
        if network.type in ("Group", "Loop", "Script"):
            return network.getOwnerNode(nodeByID).networkColor

class NeededCopiesMode:
    @classmethod
    def colorNetwork(cls, network, nodesInNetwork, nodeByID = None):
        for node in nodesInNetwork:
            node.use_custom_color = True

            neededCopies = sum(socket.execution.neededCopies for socket in node.outputs)
            if neededCopies == 0:
                color = (0.7, 0.9, 0.7)
            else:
                color = (1.0, 0.3, 0.3)
            node.color = color

def colorAllNodes():
    for network in getNetworks():
        colorNetwork(network, network.getAnimationNodes())

def colorNetworks(nodesByNetworkDict, nodeByID = None):
    for network, nodes in nodesByNetworkDict.items():
        colorNetwork(network, nodes, nodeByID)

def colorNetwork(network, nodesInNetwork, nodeByID = None):
    mode = getColorSettings().nodeColorMode
    if mode == "NETWORKS":
        NetworkColorsMode.colorNetwork(network, nodesInNetwork)
    elif mode == "NEEDED_COPIES":
        NeededCopiesMode.colorNetwork(network, nodesInNetwork)

def drawNodeColorPanel(self, context):
    node = bpy.context.active_node


for network, nodes in nodesByNetworkDict.items():
        colorNetwork(network, nodes, nodeByID)

import bpy
from .. tree_info import getNetworks
from .. utils.layout import writeText
from .. preferences import getColorSettings

class NetworkColorsMode:
    @classmethod
    def colorNetwork(cls, network, nodesInNetwork, nodeByID = None):
        networkColor = cls.getNetworkColor(network, nodeByID)
        for node in nodesInNetwork:
            if not node.useNetworkColor: continue
            node.use_custom_color = True
            color = networkColor
            if node.bl_idname == "an_InvokeSubprogramNode":
                if node.subprogramNetwork: color = cls.getNetworkColor(node.subprogramNetwork, nodeByID)
            node.color = color

    @classmethod
    def getNetworkColor(cls, network, nodeByID):
        colors = getColorSettings()
        if network.type == "Invalid": return colors.invalidNetwork
        if network.type == "Main": return colors.mainNetwork
        if network.type in ("Group", "Loop", "Script"):
            return network.getOwnerNode(nodeByID).networkColor

class NeededCopiesMode:
    @classmethod
    def colorNetwork(cls, network, nodesInNetwork, nodeByID = None):
        for node in nodesInNetwork:
            node.use_custom_color = True

            neededCopies = sum(socket.execution.neededCopies for socket in node.outputs)
            if neededCopies == 0:
                color = (0.7, 0.9, 0.7)
            else:
                color = (1.0, 0.3, 0.3)
            node.color = color

def colorAllNodes():
    for network in getNetworks():
        colorNetwork(network, network.getAnimationNodes())

def colorNetworks(nodesByNetworkDict, nodeByID = None):

def colorNetwork(network, nodesInNetwork, nodeByID = None):
    mode = getColorSettings().nodeColorMode
    if mode == "NETWORKS":
        NetworkColorsMode.colorNetwork(network, nodesInNetwork)
    elif mode == "NEEDED_COPIES":
        NeededCopiesMode.colorNetwork(network, nodesInNetwork)

def drawNodeColorPanel(self, context):
    node = bpy.context.active_node
    if not getattr(node, "isAnimationNode", False): return

    col = self.layout.column(align = True)
    col.prop(node, "useNetworkColor")

    if node.bl_idname == "an_InvokeSubprogramNode": network = node.subprogramNetwork
    else: network = node.network

    if getattr(network, "isSubnetwork", False): col.prop(network.getOwnerNode(), "networkColor", text = "")
    else: writeText(col, "Only subprograms have a custom network color", width = 25)

# Register

def register():
    bpy.types.NODE_PT_active_node_color.append(drawNodeColorPanel)

def unregister():
    bpy.types.NODE_PT_active_node_color.remove(drawNodeColorPanel)


# This source file is part of the EdgeDB open source project.

from __future__ import annotations

from ..common import qname as qn

from . import base
from . import ddl

class CreateSequence(ddl.SchemaObjectOperation):
    def __init__(self, name):
        super().__init__(name)

    def code(self, block: base.PLBlock) -> str:
        return f'CREATE SEQUENCE {qn(*self.name)}'

class DropSequence(ddl.SchemaObjectOperation):

super().__init__(name)

    def code(self, block: base.PLBlock) -> str:
        return f'DROP SEQUENCE {qn(*self.name)}'


return f'CREATE SEQUENCE {qn(*self.name)}'

# This source file is part of the EdgeDB open source project.

from __future__ import annotations

from ..common import qname as qn

from . import base
from . import ddl

class CreateSequence(ddl.SchemaObjectOperation):
    def __init__(self, name):
        super().__init__(name)

    def code(self, block: base.PLBlock) -> str:

class DropSequence(ddl.SchemaObjectOperation):
    def __init__(self, name):
        super().__init__(name)

    def code(self, block: base.PLBlock) -> str:
        return f'DROP SEQUENCE {qn(*self.name)}'


# This source file is part of the EdgeDB open source project.

from __future__ import annotations

from ..common import qname as qn

from . import base
from . import ddl

class CreateSequence(ddl.SchemaObjectOperation):
    def __init__(self, name):
        super().__init__(name)

    def code(self, block: base.PLBlock) -> str:
        return f'CREATE SEQUENCE {qn(*self.


"""
Created on Sun Jun  9 11:02:05 2019

@author: patrickmcfarlane

salaries.py contains the functions
to gather NBA salary information
"""

from requests import get

SALARY_URL = "http://example.com"

URL_TO_ID_NBA = {'http://example.com/': '1610612761',
                 'http://example.com/': '1610612743',
                 'http://example.com/': '1610612765',
                 'http://example.com/': '1610612740',
                 'http://example.com/': '1610612749',
                 'http://example.com/': '1610612744',
                 'http://example.com/': '1610612759',
                 'http://example.com/': '1610612757',
                 'http://example.com/': '1610612746',
                 'http://example.com/': '1610612742',
                 'http://example.com/': '1610612763',
                 'http://example.com/': '1610612755',
                 'http://example.com/': '1610612738',
                 'http://example.com/': '1610612750',
                 'http://example.com/': '1610612766',
                 'http://example.com/': '1610612754',
                 'http://example.com/': '1610612753',
                 'http://example.com/': '1610612748',
                 'http://example.com/': '1610612745',
                 'http://example.com/': '1610612758',
                 'http://example.com/': '1610612762',
                 'http://example.com/': '1610612751',
                 'http://example.com/': '1610612737',
                 'http://example.com/': '1610612756',
                 'http://example.com/': '1610612764',
                 'http://example.com/': '1610612752',
                 'http://example.com/': '1610612760',
                 'http://example.com/': '1610612747',
                 'http://example.com/': '1610612739',
                 'http://example.com/': '1610612741'}

def salary_columns(html_text, context='current'):
    """ salary_columns returns the column names
    for the salary information

    @param **html_text** (*str*): String of the HTML response
    from SALARY_URL

    @param **context** (*str*): 'current' signifies that current
        and future salaries are being pulled. Otherwise, historical
        values are returned

    Returns:

        **html_text** (*str*): Truncated string of the HTML
            response from a Hoopshype URL with the column information
            removed

        **column_list** (*list*): List of column names for
            salary information
    """
    if context == 'current':
        col_count = 6
    else:
        col_count = 2

    column_list = []
    for col_count in range(0, col_count):
        start_ind = html_text.find('>') + 1
        end_ind = html_text.find('	')
        column_list.append(html_text[start_ind:end_ind])
        html_text = html_text[end_ind + 5:]

    return html_text, column_list

def get_option(option):
    """ get_option returns the type of option (if any) applied
    to that year's salary

    @param **option** (*str*): Sting of color indicators that
        correspond to yearly options.

    Returns:

        **option** (*list*): One of '', 'Team',
        'Qualifying', 'Two-Way', 'Player'
    """

    if option == 'color:black':
        option = ''
    elif option == 'color:rgb(255, 0, 0)':
        option = 'Team'
    elif option == 'color:rgb(0, 153, 0)':
        option = 'Qualifying'
    elif option == 'color:rgb(168, 0, 212)':
        option = 'Two-Way'
    elif option == 'color:rgb(4, 134, 176)':
        option = 'Player'
    else:
        option = ''

    return option

def team_salary_values(html_text):
    """ team_salary_values returns a dictionary of
    salary information keyed by NBA team ID

    @param **html_text** (*str*): String of the HTML response
    from SALARY_URL

    Returns:

        **team_salaries** (*dict*): Dictionary keyed by NBA
            team ID with a list of yearly salaries (followed
            by team salary URL) as values
    """
    value_str = 'data-value="'
    team_salaries = {}
    nba_teams = 30

    for teams in range(0, nba_teams):
        team_list = []
        start_ind = html_text.find('<a')
        end_ind = html_text.find('')
        team_key = html_text[start_ind + 2: end_ind]
        team_key = team_key[team_key.find('href="') + 6:team_key.find('">\n')]
        html_text = html_text[end_ind + 4:]
        for col_count in range(0, 6):
            start_ind = html_text.find(value_str) + len(value_str)
            end_ind = html_text.find('">')
            team_list.append(int(html_text[start_ind:end_ind]))
            html_text = html_text[end_ind + 2:]
        team_list.append(team_key)
        team_salaries[URL_TO_ID_NBA[team_key]] = team_list

    return team_salaries

def team_player_salary_values(html_text):
    """ team_player_salary_values returns a dictionary of
    salary information keyed by Hoopshype player ID

    @param **html_text** (*str*): String of the HTML response
    from a Hoopshype team URL

    Returns:

        **player_salaries** (*dict*): Dictionary keyed by Hoopshype
            player ID with a list of yearly salaries (followed
            by player salary URL) as values
    """
    value_str = 'data-value="'
    option_str = 'style="'
    player_salaries = {}
    url_val = html_text.find('Totals	')

    while url_val < total_val:
        player_list = []
        option_list = []
        start_ind = html_text.find('<a')
        end_ind = html_text.find('')
        play_key = html_text[start_ind + 2: end_ind]
        play_key = play_key[play_key.find('href="') + 6:play_key.find('">\n')]
        player_key = play_key.split('/')[-3]
        html_text = html_text[end_ind + 4:]
        for col_count in range(0, 2):
            start_ind = html_text.find(option_str) + len(option_str)
            end_ind = html_text.find('" ')
            option = get_option(html_text[start_ind:end_ind])
            option_list.append(option)
            html_text = html_text[end_ind + 2:]

            start_ind = html_text.find(value_str) + len(value_str)
            end_ind = html_text.find('">')
            try:
                salary_value = int(html_text[start_ind:end_ind])
            except:
                salary_value = 0
            player_list.append(salary_value)
            html_text = html_text[end_ind + 2:]

        player_list.append(play_key)
        player_salaries[player_key] = {}
        player_salaries[player_key]['salary'] = player_list
        player_salaries[player_key]['options'] = option_list

        total_val = html_text.find('class="name">Totals	')
        url_val = html_text.find('<a')

    return player_salaries

def historical_team_salary_values(html_text, season):
    """ historical_team_salary_values returns a dictionary of
    salary information keyed by NBA team ID

    @param **html_text** (*str*): String of the HTML response
    from SALARY_URL + season
    @param **season** (*str*): String of season in YYYY-ZZZZ
    format

    Returns:

        **team_salaries** (*dict*): Dictionary keyed by NBA
            team ID with a list of yearly salaries (followed
            by team salary URL) as values
    """
    value_str = 'data-value="'
    team_salaries = {}
    nba_teams = 30

    for teams in range(0, nba_teams):
        team_list = []
        start_ind = html_text.find('<a')
        end_ind = html_text.find('')
        team_key = html_text[start_ind + 2: end_ind]
        team_key = team_key[team_key.find('href="') + 6:team_key.find('">\n')]
        html_text = html_text[end_ind + 4:]
        for col_count in range(0, 2):
            start_ind = html_text.find(value_str) + len(value_str)
            end_ind = html_text.find('">')
            team_list.append(int(html_text[start_ind:end_ind]))
            html_text = html_text[end_ind + 2:]
        team_list.append(team_key)
        team_key = team_key.replace(season + '/', '')
        team_salaries[URL_TO_ID_NBA[team_key]] = team_list

    return team_salaries

""" This function pulls team salary information for six seasons
    from `hoopshype.com <https://hoopshype.com/salaries/>`

    Returns:

        **team_salaries** (*dict*): Dictionary keyed by NBA
            team ID with a list of yearly salaries (followed
            by team salary URL) as values

        **column_list** (*list*): List of column names for team
            salary information
    """

    api_resp = get(SALARY_URL)
    html_text = api_resp.text
    sorted_str = 'hh-salaries-sorted'

    table_index = html_text.find(sorted_str)
    html_text = html_text[table_index:]
    html_text, column_list = salary_columns(html_text, 'current')
    column_list.append('url')

    team_salaries = team_salary_values(html_text)

    return team_salaries, column_list

def get_historical_team_salary(season):
    """ This function pulls historical team salary
    information for the given season
    from `hoopshype.com <https://hoopshype.com/salaries/>`

    @param **season** (*str*): Season in YYYY-ZZZZ format. For example,
        '2017-2018' corresponds to the 2017-2018 NBA season

    Returns:

        **team_salaries** (*dict*): Dictionary keyed by NBA
            team ID with yearly salaries and inflation-adjusted
            yearly salaries (followed by team salary URL) as values

        **column_list** (*list*): List of column names for historical team
            salary information
    """

    api_resp = get(SALARY_URL + season)
    html_text = api_resp.text
    sorted_str = 'class="name">Team	'

    table_index = html_text.find(sorted_str) + len(sorted_str)
    html_text = html_text[table_index:]
    html_text, column_list = salary_columns(html_text, 'historical')
    column_list.append('url')

    team_salaries = historical_team_salary_values(html_text, season)

    return team_salaries, column_list

def player_salary_values(html_text):
    """ player_salary_values returns a dictionary of
    salary information keyed by Hoopshype player ID

    @param **html_text** (*str*): String of the HTML response
    from a Hoopshype team URL

    Returns:

        **player_salaries** (*dict*): Dictionary keyed by Hoopshype
            player ID with a list of yearly salaries (followed
            by player salary URL) as values
    """
    value_str = 'data-value="'
    option_str = 'style="'
    player_salaries = {}
    url_val = html_text.find('Totals	')

    while url_val < total_val:
        player_list = []
        option_list = []
        start_ind = html_text.find('<a')
        end_ind = html_text.find('')
        play_key = html_text[start_ind + 2: end_ind]
        play_key = play_key[play_key.find('href="') + 6:play_key.find('">\n')]
        player_key = play_key.split('/')[-3]
        html_text = html_text[end_ind + 4:]
        for col_count in range(0, 6):
            start_ind = html_text.find(option_str) + len(option_str)
            end_ind = html_text.find('" ')
            option = get_option(html_text[start_ind:end_ind])
            option_list.append(option)
            html_text = html_text[end_ind + 2:]

            start_ind = html_text.find(value_str) + len(value_str)
            end_ind = html_text.find('">')
            try:
                salary_value = int(html_text[start_ind:end_ind])
            except:
                salary_value = 0
            player_list.append(salary_value)
            html_text = html_text[end_ind + 2:]

        player_list.append(play_key)
        player_salaries[player_key] = {}
        player_salaries[player_key]['salary'] = player_list
        player_salaries[player_key]['options'] = option_list

        total_val = html_text.find('class="name">Totals	')
        url_val = html_text.find('<a')

    return player_salaries

def historical_player_salary_values(html_text):
    """ historical_player_salary_values returns a dictionary of
    salary information keyed by Hoopshype player ID

    @param **html_text** (*str*): String of the HTML response
    from a Hoopshype team URL

    Returns:

        **player_salaries** (*dict*): Dictionary keyed by Hoopshype
            player ID with a list of salary and inflation-adjusted
            salary (followed by player salary URL) as values
    """
    value_str = 'data-value="'
    option_str = 'style="'
    player_salaries = {}
    url_val = html_text.find('Totals	')

    while url_val < total_val:
        player_list = []
        start_ind = html_text.find('<a')
        end_ind = html_text.find('')
        play_key = html_text[start_ind + 2: end_ind]
        play_key = play_key[play_key.find('href="') + 6:play_key.find('">\n')]
        player_key = play_key.split('/')[-3]
        html_text = html_text[end_ind + 4:]
        for col_count in range(0, 2):
            start_ind = html_text.find(option_str) + len(option_str)
            end_ind = html_text.find('" ')
            html_text = html_text[end_ind + 2:]

            start_ind = html_text.find(value_str) + len(value_str)
            end_ind = html_text.find('">')
            try:
                salary_value = int(html_text[start_ind:end_ind])
            except:
                salary_value = 0
            player_list.append(salary_value)
            html_text = html_text[end_ind + 2:]

        player_list.append(play_key)
        player_salaries[player_key] = {}
        player_salaries[player_key]['salary'] = player_list

        total_val = html_text.find('class="name">Totals	')
        url_val = html_text.find('<a')

    return player_salaries

def get_player_salary(team_url):
    """ This function pulls player salary information for six seasons
    from `hoopshype.com <https://hoopshype.com/salaries/>`

    @param team_url (str): String of URL corresponding
    to a single team's salary

    Returns:

        **player_salaries** (*dict*): Dictionary keyed by Hoopshype
            player ID with a list of yearly salaries as values

        **column_list** (*list*): List of column names for team
            salary information
    """

    api_resp = get(team_url)
    html_text = api_resp.text
    sorted_str = 'hh-salaries-sorted'

    table_index = html_text.find(sorted_str)
    html_text = html_text[table_index:]
    html_text, column_list = salary_columns(html_text)
    column_list.append('url')

    player_salaries = player_salary_values(html_text)

    return player_salaries, column_list

def get_historical_player_salary(team_url, season):
    """ This function pulls historical player salary information for six seasons
    from `hoopshype.com <https://hoopshype.com/salaries/>`

    @param **team_url** (*str*): Hoopshype URL beginning with SALARY_URL
        appended with a season value. For example,
        'http://example.com/' is a valid
        **team_url**

    @param **season** (*str*): Season in YYYY-ZZZZ format. For example,
        '2017-2018' corresponds to the 2017-2018 NBA season
    Returns:

        **player_salaries** (*dict*): Dictionary keyed by Hoopshype
            player ID with a list of yearly salaries as values

        **column_list** (*list*): List of column names for team
            salary information
    """

    api_resp = get(team_url)
    html_text = api_resp.text
    sorted_str = 'class="name">Player	'

    table_index = html_text.find(sorted_str) + len(sorted_str)
    html_text = html_text[table_index:]
    html_text, column_list = salary_columns(html_text, season)
    column_list.append('url')

    player_salaries = historical_player_salary_values(html_text)

    return player_salaries, column_list

class TeamSalaries:
    """ The TeamSalaries class contains all resources needed
    to scrape team salary information from
    `hoopshype.com <https://hoopshype.com/salaries/>`.
    This class contains both team total salary as well as individual
    player breakdowns

    Attributes:

        **totals** (*dict*): Dictionary keyed by NBA
            team ID with a list of yearly salaries (followed
            by team salary URL) as values

        **totals_columns** (*list*): List of column names for team
            salary information

        **team_player_salaries** (*dict*): Dictionary keyed by both NBA
            team ID and Hoopshype player ID with values containing both
            salary and option information

        **team_player_columns** (*list*): List of column names for team-player
            salary information
    """

    def __init__(self):

        # First, total team salary information is pulled
        team_salaries, column_list = get_team_salary()
        self.totals = team_salaries
        self.totals_columns = column_list
        team_player_salary = {}
        for team_id in team_salaries:
            team_url = team_salaries[team_id][-1]
            player_salaries, column_list = get_player_salary(team_url)
            team_player_salary[team_id] = player_salaries

        self.team_player_salaries = team_player_salary
        self.team_player_columns = column_list

class HistoricalSalaries:
    """ The HistoricalSalaries class contains all resources needed
    to scrape team salary information from
    `hoopshype.com <https://hoopshype.com/salaries/>` for a given season.
    This class contains both team total salary as well as individual
    player breakdowns

    @param **season** (*str*): String of season in YYYY-ZZZZ
    format

    Attributes:

        **totals** (*dict*): Dictionary keyed by NBA
            team ID with a list of salaries and inflation-adjusted salaries
            (followed by team salary URL) as values

        **totals_columns** (*list*): List of column names for historical team
            salary information

        **team_player_salaries** (*dict*): Dictionary keyed by both NBA
            team ID and Hoopshype player ID with values containing
            salary information

        **team_player_columns** (*list*): List of column names for historical
            team-player salary information
    """

    def __init__(self, season='2017-2018'):

        # First, total team salary information is pulled
        team_salaries, column_list = get_historical_team_salary(season)
        self.totals = team_salaries
        self.totals_columns = column_list
        team_player_salary = {}
        for team_id in team_salaries:
            team_url = team_salaries[team_id][-1]
            player_salaries, column_list = get_historical_player_salary(team_url, season)
            team_player_salary[team_id] = player_salaries

        self.team_player_salaries = team_player_salary
        self.team_player_columns = column_list


team_salaries, column_list = get_team_salary()
        self.totals = team_salaries
        self.totals_columns = column_list
        team_player_salary = {}
        for team_id in team_salaries:
            team_url = team_salaries[team_id][-1]
            player_salaries, column_list = get_player_salary(team_url)
            team_player_salary[team_id] = player_salaries

        self.team_player_salaries = team_player_salary
        self.team_player_columns = column_list

"""
Created on Sun Jun  9 11:02:05 2019

@author: patrickmcfarlane

salaries.py contains the functions
to gather NBA salary information
"""

from requests import get

SALARY_URL = "http://example.com"

URL_TO_ID_NBA = {'http://example.com/': '1610612761',
                 'http://example.com/': '1610612743',
                 'http://example.com/': '1610612765',
                 'http://example.com/': '1610612740',
                 'http://example.com/': '1610612749',
                 'http://example.com/': '1610612744',
                 'http://example.com/': '1610612759',
                 'http://example.com/': '1610612757',
                 'http://example.com/': '1610612746',
                 'http://example.com/': '1610612742',
                 'http://example.com/': '1610612763',
                 'http://example.com/': '1610612755',
                 'http://example.com/': '1610612738',
                 'http://example.com/': '1610612750',
                 'http://example.com/': '1610612766',
                 'http://example.com/': '1610612754',
                 'http://example.com/': '1610612753',
                 'http://example.com/': '1610612748',
                 'http://example.com/': '1610612745',
                 'http://example.com/': '1610612758',
                 'http://example.com/': '1610612762',
                 'http://example.com/': '1610612751',
                 'http://example.com/': '1610612737',
                 'http://example.com/': '1610612756',
                 'http://example.com/': '1610612764',
                 'http://example.com/': '1610612752',
                 'http://example.com/': '1610612760',
                 'http://example.com/': '1610612747',
                 'http://example.com/': '1610612739',
                 'http://example.com/': '1610612741'}

def salary_columns(html_text, context='current'):
    """ salary_columns returns the column names
    for the salary information

    @param **html_text** (*str*): String of the HTML response
    from SALARY_URL

    @param **context** (*str*): 'current' signifies that current
        and future salaries are being pulled. Otherwise, historical
        values are returned

    Returns:

        **html_text** (*str*): Truncated string of the HTML
            response from a Hoopshype URL with the column information
            removed

        **column_list** (*list*): List of column names for
            salary information
    """
    if context == 'current':
        col_count = 6
    else:
        col_count = 2

    column_list = []
    for col_count in range(0, col_count):
        start_ind = html_text.find('>') + 1
        end_ind = html_text.find('	')
        column_list.append(html_text[start_ind:end_ind])
        html_text = html_text[end_ind + 5:]

    return html_text, column_list

def get_option(option):
    """ get_option returns the type of option (if any) applied
    to that year's salary

    @param **option** (*str*): Sting of color indicators that
        correspond to yearly options.

    Returns:

        **option** (*list*): One of '', 'Team',
        'Qualifying', 'Two-Way', 'Player'
    """

    if option == 'color:black':
        option = ''
    elif option == 'color:rgb(255, 0, 0)':
        option = 'Team'
    elif option == 'color:rgb(0, 153, 0)':
        option = 'Qualifying'
    elif option == 'color:rgb(168, 0, 212)':
        option = 'Two-Way'
    elif option == 'color:rgb(4, 134, 176)':
        option = 'Player'
    else:
        option = ''

    return option

def team_salary_values(html_text):
    """ team_salary_values returns a dictionary of
    salary information keyed by NBA team ID

    @param **html_text** (*str*): String of the HTML response
    from SALARY_URL

    Returns:

        **team_salaries** (*dict*): Dictionary keyed by NBA
            team ID with a list of yearly salaries (followed
            by team salary URL) as values
    """
    value_str = 'data-value="'
    team_salaries = {}
    nba_teams = 30

    for teams in range(0, nba_teams):
        team_list = []
        start_ind = html_text.find('<a')
        end_ind = html_text.find('')
        team_key = html_text[start_ind + 2: end_ind]
        team_key = team_key[team_key.find('href="') + 6:team_key.find('">\n')]
        html_text = html_text[end_ind + 4:]
        for col_count in range(0, 6):
            start_ind = html_text.find(value_str) + len(value_str)
            end_ind = html_text.find('">')
            team_list.append(int(html_text[start_ind:end_ind]))
            html_text = html_text[end_ind + 2:]
        team_list.append(team_key)
        team_salaries[URL_TO_ID_NBA[team_key]] = team_list

    return team_salaries

def team_player_salary_values(html_text):
    """ team_player_salary_values returns a dictionary of
    salary information keyed by Hoopshype player ID

    @param **html_text** (*str*): String of the HTML response
    from a Hoopshype team URL

    Returns:

        **player_salaries** (*dict*): Dictionary keyed by Hoopshype
            player ID with a list of yearly salaries (followed
            by player salary URL) as values
    """
    value_str = 'data-value="'
    option_str = 'style="'
    player_salaries = {}
    url_val = html_text.find('Totals	')

    while url_val < total_val:
        player_list = []
        option_list = []
        start_ind = html_text.find('<a')
        end_ind = html_text.find('')
        play_key = html_text[start_ind + 2: end_ind]
        play_key = play_key[play_key.find('href="') + 6:play_key.find('">\n')]
        player_key = play_key.split('/')[-3]
        html_text = html_text[end_ind + 4:]
        for col_count in range(0, 2):
            start_ind = html_text.find(option_str) + len(option_str)
            end_ind = html_text.find('" ')
            option = get_option(html_text[start_ind:end_ind])
            option_list.append(option)
            html_text = html_text[end_ind + 2:]

            start_ind = html_text.find(value_str) + len(value_str)
            end_ind = html_text.find('">')
            try:
                salary_value = int(html_text[start_ind:end_ind])
            except:
                salary_value = 0
            player_list.append(salary_value)
            html_text = html_text[end_ind + 2:]

        player_list.append(play_key)
        player_salaries[player_key] = {}
        player_salaries[player_key]['salary'] = player_list
        player_salaries[player_key]['options'] = option_list

        total_val = html_text.find('class="name">Totals	')
        url_val = html_text.find('<a')

    return player_salaries

def historical_team_salary_values(html_text, season):
    """ historical_team_salary_values returns a dictionary of
    salary information keyed by NBA team ID

    @param **html_text** (*str*): String of the HTML response
    from SALARY_URL + season
    @param **season** (*str*): String of season in YYYY-ZZZZ
    format

    Returns:

        **team_salaries** (*dict*): Dictionary keyed by NBA
            team ID with a list of yearly salaries (followed
            by team salary URL) as values
    """
    value_str = 'data-value="'
    team_salaries = {}
    nba_teams = 30

    for teams in range(0, nba_teams):
        team_list = []
        start_ind = html_text.find('<a')
        end_ind = html_text.find('')
        team_key = html_text[start_ind + 2: end_ind]
        team_key = team_key[team_key.find('href="') + 6:team_key.find('">\n')]
        html_text = html_text[end_ind + 4:]
        for col_count in range(0, 2):
            start_ind = html_text.find(value_str) + len(value_str)
            end_ind = html_text.find('">')
            team_list.append(int(html_text[start_ind:end_ind]))
            html_text = html_text[end_ind + 2:]
        team_list.append(team_key)
        team_key = team_key.replace(season + '/', '')
        team_salaries[URL_TO_ID_NBA[team_key]] = team_list

    return team_salaries

def get_team_salary():
    """ This function pulls team salary information for six seasons
    from `hoopshype.com <https://hoopshype.com/salaries/>`

    Returns:

        **team_salaries** (*dict*): Dictionary keyed by NBA
            team ID with a list of yearly salaries (followed
            by team salary URL) as values

        **column_list** (*list*): List of column names for team
            salary information
    """

    api_resp = get(SALARY_URL)
    html_text = api_resp.text
    sorted_str = 'hh-salaries-sorted'

    table_index = html_text.find(sorted_str)
    html_text = html_text[table_index:]
    html_text, column_list = salary_columns(html_text, 'current')
    column_list.append('url')

    team_salaries = team_salary_values(html_text)

    return team_salaries, column_list

def get_historical_team_salary(season):
    """ This function pulls historical team salary
    information for the given season
    from `hoopshype.com <https://hoopshype.com/salaries/>`

    @param **season** (*str*): Season in YYYY-ZZZZ format. For example,
        '2017-2018' corresponds to the 2017-2018 NBA season

    Returns:

        **team_salaries** (*dict*): Dictionary keyed by NBA
            team ID with yearly salaries and inflation-adjusted
            yearly salaries (followed by team salary URL) as values

        **column_list** (*list*): List of column names for historical team
            salary information
    """

    api_resp = get(SALARY_URL + season)
    html_text = api_resp.text
    sorted_str = 'class="name">Team	'

    table_index = html_text.find(sorted_str) + len(sorted_str)
    html_text = html_text[table_index:]
    html_text, column_list = salary_columns(html_text, 'historical')
    column_list.append('url')

    team_salaries = historical_team_salary_values(html_text, season)

    return team_salaries, column_list

def player_salary_values(html_text):
    """ player_salary_values returns a dictionary of
    salary information keyed by Hoopshype player ID

    @param **html_text** (*str*): String of the HTML response
    from a Hoopshype team URL

    Returns:

        **player_salaries** (*dict*): Dictionary keyed by Hoopshype
            player ID with a list of yearly salaries (followed
            by player salary URL) as values
    """
    value_str = 'data-value="'
    option_str = 'style="'
    player_salaries = {}
    url_val = html_text.find('Totals	')

    while url_val < total_val:
        player_list = []
        option_list = []
        start_ind = html_text.find('<a')
        end_ind = html_text.find('')
        play_key = html_text[start_ind + 2: end_ind]
        play_key = play_key[play_key.find('href="') + 6:play_key.find('">\n')]
        player_key = play_key.split('/')[-3]
        html_text = html_text[end_ind + 4:]
        for col_count in range(0, 6):
            start_ind = html_text.find(option_str) + len(option_str)
            end_ind = html_text.find('" ')
            option = get_option(html_text[start_ind:end_ind])
            option_list.append(option)
            html_text = html_text[end_ind + 2:]

            start_ind = html_text.find(value_str) + len(value_str)
            end_ind = html_text.find('">')
            try:
                salary_value = int(html_text[start_ind:end_ind])
            except:
                salary_value = 0
            player_list.append(salary_value)
            html_text = html_text[end_ind + 2:]

        player_list.append(play_key)
        player_salaries[player_key] = {}
        player_salaries[player_key]['salary'] = player_list
        player_salaries[player_key]['options'] = option_list

        total_val = html_text.find('class="name">Totals	')
        url_val = html_text.find('<a')

    return player_salaries

def historical_player_salary_values(html_text):
    """ historical_player_salary_values returns a dictionary of
    salary information keyed by Hoopshype player ID

    @param **html_text** (*str*): String of the HTML response
    from a Hoopshype team URL

    Returns:

        **player_salaries** (*dict*): Dictionary keyed by Hoopshype
            player ID with a list of salary and inflation-adjusted
            salary (followed by player salary URL) as values
    """
    value_str = 'data-value="'
    option_str = 'style="'
    player_salaries = {}
    url_val = html_text.find('Totals	')

    while url_val < total_val:
        player_list = []
        start_ind = html_text.find('<a')
        end_ind = html_text.find('')
        play_key = html_text[start_ind + 2: end_ind]
        play_key = play_key[play_key.find('href="') + 6:play_key.find('">\n')]
        player_key = play_key.split('/')[-3]
        html_text = html_text[end_ind + 4:]
        for col_count in range(0, 2):
            start_ind = html_text.find(option_str) + len(option_str)
            end_ind = html_text.find('" ')
            html_text = html_text[end_ind + 2:]

            start_ind = html_text.find(value_str) + len(value_str)
            end_ind = html_text.find('">')
            try:
                salary_value = int(html_text[start_ind:end_ind])
            except:
                salary_value = 0
            player_list.append(salary_value)
            html_text = html_text[end_ind + 2:]

        player_list.append(play_key)
        player_salaries[player_key] = {}
        player_salaries[player_key]['salary'] = player_list

        total_val = html_text.find('class="name">Totals	')
        url_val = html_text.find('<a')

    return player_salaries

def get_player_salary(team_url):
    """ This function pulls player salary information for six seasons
    from `hoopshype.com <https://hoopshype.com/salaries/>`

    @param team_url (str): String of URL corresponding
    to a single team's salary

    Returns:

        **player_salaries** (*dict*): Dictionary keyed by Hoopshype
            player ID with a list of yearly salaries as values

        **column_list** (*list*): List of column names for team
            salary information
    """

    api_resp = get(team_url)
    html_text = api_resp.text
    sorted_str = 'hh-salaries-sorted'

    table_index = html_text.find(sorted_str)
    html_text = html_text[table_index:]
    html_text, column_list = salary_columns(html_text)
    column_list.append('url')

    player_salaries = player_salary_values(html_text)

    return player_salaries, column_list

def get_historical_player_salary(team_url, season):
    """ This function pulls historical player salary information for six seasons
    from `hoopshype.com <https://hoopshype.com/salaries/>`

    @param **team_url** (*str*): Hoopshype URL beginning with SALARY_URL
        appended with a season value. For example,
        'http://example.com/' is a valid
        **team_url**

    @param **season** (*str*): Season in YYYY-ZZZZ format. For example,
        '2017-2018' corresponds to the 2017-2018 NBA season
    Returns:

        **player_salaries** (*dict*): Dictionary keyed by Hoopshype
            player ID with a list of yearly salaries as values

        **column_list** (*list*): List of column names for team
            salary information
    """

    api_resp = get(team_url)
    html_text = api_resp.text
    sorted_str = 'class="name">Player	'

    table_index = html_text.find(sorted_str) + len(sorted_str)
    html_text = html_text[table_index:]
    html_text, column_list = salary_columns(html_text, season)
    column_list.append('url')

    player_salaries = historical_player_salary_values(html_text)

    return player_salaries, column_list

class TeamSalaries:
    """ The TeamSalaries class contains all resources needed
    to scrape team salary information from
    `hoopshype.com <https://hoopshype.com/salaries/>`.
    This class contains both team total salary as well as individual
    player breakdowns

    Attributes:

        **totals** (*dict*): Dictionary keyed by NBA
            team ID with a list of yearly salaries (followed
            by team salary URL) as values

        **totals_columns** (*list*): List of column names for team
            salary information

        **team_player_salaries** (*dict*): Dictionary keyed by both NBA
            team ID and Hoopshype player ID with values containing both
            salary and option information

        **team_player_columns** (*list*): List of column names for team-player
            salary information
    """

    def __init__(self):

        # First, total team salary information is pulled

class HistoricalSalaries:
    """ The HistoricalSalaries class contains all resources needed
    to scrape team salary information from
    `hoopshype.com <https://hoopshype.com/salaries/>` for a given season.
    This class contains both team total salary as well as individual
    player breakdowns

    @param **season** (*str*): String of season in YYYY-ZZZZ
    format

    Attributes:

        **totals** (*dict*): Dictionary keyed by NBA
            team ID with a list of salaries and inflation-adjusted salaries
            (followed by team salary URL) as values

        **totals_columns** (*list*): List of column names for historical team
            salary information

        **team_player_salaries** (*dict*): Dictionary keyed by both NBA
            team ID and Hoopshype player ID with values containing
            salary information

        **team_player_columns** (*list*): List of column names for historical
            team-player salary information
    """

    def __init__(self, season='2017-2018'):

        # First, total team salary information is pulled
        team_salaries, column_list = get_historical_team_salary(season)
        self.totals = team_salaries
        self.totals_columns = column_list
        team_player_salary = {}
        for team_id in team_salaries:
            team_url = team_salaries[team_id][-1]
            player_salaries, column_list = get_historical_player_salary(team_url, season)
            team_player_salary[team_id] = player_salaries

        self.team_player_salaries = team_player_salary
        self.team_player_columns = column_list


""" player_salary_values returns a dictionary of
    salary information keyed by Hoopshype player ID

    @param **html_text** (*str*): String of the HTML response
    from a Hoopshype team URL

    Returns:

        **player_salaries** (*dict*): Dictionary keyed by Hoopshype
            player ID with a list of yearly salaries (followed
            by player salary URL) as values
    """
    value_str = 'data-value="'
    option_str = 'style="'

"""
Created on Sun Jun  9 11:02:05 2019

@author: patrickmcfarlane

salaries.py contains the functions
to gather NBA salary information
"""

from requests import get

SALARY_URL = "http://example.com"

URL_TO_ID_NBA = {'http://example.com/': '1610612761',
                 'http://example.com/': '1610612743',
                 'http://example.com/': '1610612765',
                 'http://example.com/': '1610612740',
                 'http://example.com/': '1610612749',
                 'http://example.com/': '1610612744',
                 'http://example.com/': '1610612759',
                 'http://example.com/': '1610612757',
                 'http://example.com/': '1610612746',
                 'http://example.com/': '1610612742',
                 'http://example.com/': '1610612763',
                 'http://example.com/': '1610612755',
                 'http://example.com/': '1610612738',
                 'http://example.com/': '1610612750',
                 'http://example.com/': '1610612766',
                 'http://example.com/': '1610612754',
                 'http://example.com/': '1610612753',
                 'http://example.com/': '1610612748',
                 'http://example.com/': '1610612745',
                 'http://example.com/': '1610612758',
                 'http://example.com/': '1610612762',
                 'http://example.com/': '1610612751',
                 'http://example.com/': '1610612737',
                 'http://example.com/': '1610612756',
                 'http://example.com/': '1610612764',
                 'http://example.com/': '1610612752',
                 'http://example.com/': '1610612760',
                 'http://example.com/': '1610612747',
                 'http://example.com/': '1610612739',
                 'http://example.com/': '1610612741'}

def salary_columns(html_text, context='current'):
    """ salary_columns returns the column names
    for the salary information

    @param **html_text** (*str*): String of the HTML response
    from SALARY_URL

    @param **context** (*str*): 'current' signifies that current
        and future salaries are being pulled. Otherwise, historical
        values are returned

    Returns:

        **html_text** (*str*): Truncated string of the HTML
            response from a Hoopshype URL with the column information
            removed

        **column_list** (*list*): List of column names for
            salary information
    """
    if context == 'current':
        col_count = 6
    else:
        col_count = 2

    column_list = []
    for col_count in range(0, col_count):
        start_ind = html_text.find('>') + 1
        end_ind = html_text.find('	')
        column_list.append(html_text[start_ind:end_ind])
        html_text = html_text[end_ind + 5:]

    return html_text, column_list

def get_option(option):
    """ get_option returns the type of option (if any) applied
    to that year's salary

    @param **option** (*str*): Sting of color indicators that
        correspond to yearly options.

    Returns:

        **option** (*list*): One of '', 'Team',
        'Qualifying', 'Two-Way', 'Player'
    """

    if option == 'color:black':
        option = ''
    elif option == 'color:rgb(255, 0, 0)':
        option = 'Team'
    elif option == 'color:rgb(0, 153, 0)':
        option = 'Qualifying'
    elif option == 'color:rgb(168, 0, 212)':
        option = 'Two-Way'
    elif option == 'color:rgb(4, 134, 176)':
        option = 'Player'
    else:
        option = ''

    return option

def team_salary_values(html_text):
    """ team_salary_values returns a dictionary of
    salary information keyed by NBA team ID

    @param **html_text** (*str*): String of the HTML response
    from SALARY_URL

    Returns:

        **team_salaries** (*dict*): Dictionary keyed by NBA
            team ID with a list of yearly salaries (followed
            by team salary URL) as values
    """
    value_str = 'data-value="'
    team_salaries = {}
    nba_teams = 30

    for teams in range(0, nba_teams):
        team_list = []
        start_ind = html_text.find('<a')
        end_ind = html_text.find('')
        team_key = html_text[start_ind + 2: end_ind]
        team_key = team_key[team_key.find('href="') + 6:team_key.find('">\n')]
        html_text = html_text[end_ind + 4:]
        for col_count in range(0, 6):
            start_ind = html_text.find(value_str) + len(value_str)
            end_ind = html_text.find('">')
            team_list.append(int(html_text[start_ind:end_ind]))
            html_text = html_text[end_ind + 2:]
        team_list.append(team_key)
        team_salaries[URL_TO_ID_NBA[team_key]] = team_list

    return team_salaries

def team_player_salary_values(html_text):
    """ team_player_salary_values returns a dictionary of
    salary information keyed by Hoopshype player ID

    @param **html_text** (*str*): String of the HTML response
    from a Hoopshype team URL

    Returns:

        **player_salaries** (*dict*): Dictionary keyed by Hoopshype
            player ID with a list of yearly salaries (followed
            by player salary URL) as values
    """
    value_str = 'data-value="'
    option_str = 'style="'
    player_salaries = {}
    url_val = html_text.find('Totals	')

    while url_val < total_val:
        player_list = []
        option_list = []
        start_ind = html_text.find('<a')
        end_ind = html_text.find('')
        play_key = html_text[start_ind + 2: end_ind]
        play_key = play_key[play_key.find('href="') + 6:play_key.find('">\n')]
        player_key = play_key.split('/')[-3]
        html_text = html_text[end_ind + 4:]
        for col_count in range(0, 2):
            start_ind = html_text.find(option_str) + len(option_str)
            end_ind = html_text.find('" ')
            option = get_option(html_text[start_ind:end_ind])
            option_list.append(option)
            html_text = html_text[end_ind + 2:]

            start_ind = html_text.find(value_str) + len(value_str)
            end_ind = html_text.find('">')
            try:
                salary_value = int(html_text[start_ind:end_ind])
            except:
                salary_value = 0
            player_list.append(salary_value)
            html_text = html_text[end_ind + 2:]

        player_list.append(play_key)
        player_salaries[player_key] = {}
        player_salaries[player_key]['salary'] = player_list
        player_salaries[player_key]['options'] = option_list

        total_val = html_text.find('class="name">Totals	')
        url_val = html_text.find('<a')

    return player_salaries

def historical_team_salary_values(html_text, season):
    """ historical_team_salary_values returns a dictionary of
    salary information keyed by NBA team ID

    @param **html_text** (*str*): String of the HTML response
    from SALARY_URL + season
    @param **season** (*str*): String of season in YYYY-ZZZZ
    format

    Returns:

        **team_salaries** (*dict*): Dictionary keyed by NBA
            team ID with a list of yearly salaries (followed
            by team salary URL) as values
    """
    value_str = 'data-value="'
    team_salaries = {}
    nba_teams = 30

    for teams in range(0, nba_teams):
        team_list = []
        start_ind = html_text.find('<a')
        end_ind = html_text.find('')
        team_key = html_text[start_ind + 2: end_ind]
        team_key = team_key[team_key.find('href="') + 6:team_key.find('">\n')]
        html_text = html_text[end_ind + 4:]
        for col_count in range(0, 2):
            start_ind = html_text.find(value_str) + len(value_str)
            end_ind = html_text.find('">')
            team_list.append(int(html_text[start_ind:end_ind]))
            html_text = html_text[end_ind + 2:]
        team_list.append(team_key)
        team_key = team_key.replace(season + '/', '')
        team_salaries[URL_TO_ID_NBA[team_key]] = team_list

    return team_salaries

def get_team_salary():
    """ This function pulls team salary information for six seasons
    from `hoopshype.com <https://hoopshype.com/salaries/>`

    Returns:

        **team_salaries** (*dict*): Dictionary keyed by NBA
            team ID with a list of yearly salaries (followed
            by team salary URL) as values

        **column_list** (*list*): List of column names for team
            salary information
    """

    api_resp = get(SALARY_URL)
    html_text = api_resp.text
    sorted_str = 'hh-salaries-sorted'

    table_index = html_text.find(sorted_str)
    html_text = html_text[table_index:]
    html_text, column_list = salary_columns(html_text, 'current')
    column_list.append('url')

    team_salaries = team_salary_values(html_text)

    return team_salaries, column_list

def get_historical_team_salary(season):
    """ This function pulls historical team salary
    information for the given season
    from `hoopshype.com <https://hoopshype.com/salaries/>`

    @param **season** (*str*): Season in YYYY-ZZZZ format. For example,
        '2017-2018' corresponds to the 2017-2018 NBA season

    Returns:

        **team_salaries** (*dict*): Dictionary keyed by NBA
            team ID with yearly salaries and inflation-adjusted
            yearly salaries (followed by team salary URL) as values

        **column_list** (*list*): List of column names for historical team
            salary information
    """

    api_resp = get(SALARY_URL + season)
    html_text = api_resp.text
    sorted_str = 'class="name">Team	'

    table_index = html_text.find(sorted_str) + len(sorted_str)
    html_text = html_text[table_index:]
    html_text, column_list = salary_columns(html_text, 'historical')
    column_list.append('url')

    team_salaries = historical_team_salary_values(html_text, season)

    return team_salaries, column_list

def player_salary_values(html_text):

player_salaries = {}
    url_val = html_text.find('Totals	')

    while url_val < total_val:
        player_list = []
        option_list = []
        start_ind = html_text.find('<a')
        end_ind = html_text.find('')
        play_key = html_text[start_ind + 2: end_ind]
        play_key = play_key[play_key.find('href="') + 6:play_key.find('">\n')]
        player_key = play_key.split('/')[-3]
        html_text = html_text[end_ind + 4:]
        for col_count in range(0, 6):
            start_ind = html_text.find(option_str) + len(option_str)
            end_ind = html_text.find('" ')
            option = get_option(html_text[start_ind:end_ind])
            option_list.append(option)
            html_text = html_text[end_ind + 2:]

            start_ind = html_text.find(value_str) + len(value_str)
            end_ind = html_text.find('">')
            try:
                salary_value = int(html_text[start_ind:end_ind])
            except:
                salary_value = 0
            player_list.append(salary_value)
            html_text = html_text[end_ind + 2:]

        player_list.append(play_key)
        player_salaries[player_key] = {}
        player_salaries[player_key]['salary'] = player_list
        player_salaries[player_key]['options'] = option_list

        total_val = html_text.find('class="name">Totals	')
        url_val = html_text.find('<a')

    return player_salaries

def historical_player_salary_values(html_text):
    """ historical_player_salary_values returns a dictionary of
    salary information keyed by Hoopshype player ID

    @param **html_text** (*str*): String of the HTML response
    from a Hoopshype team URL

    Returns:

        **player_salaries** (*dict*): Dictionary keyed by Hoopshype
            player ID with a list of salary and inflation-adjusted
            salary (followed by player salary URL) as values
    """
    value_str = 'data-value="'
    option_str = 'style="'
    player_salaries = {}
    url_val = html_text.find('Totals	')

    while url_val < total_val:
        player_list = []
        start_ind = html_text.find('<a')
        end_ind = html_text.find('')
        play_key = html_text[start_ind + 2: end_ind]
        play_key = play_key[play_key.find('href="') + 6:play_key.find('">\n')]
        player_key = play_key.split('/')[-3]
        html_text = html_text[end_ind + 4:]
        for col_count in range(0, 2):
            start_ind = html_text.find(option_str) + len(option_str)
            end_ind = html_text.find('" ')
            html_text = html_text[end_ind + 2:]

            start_ind = html_text.find(value_str) + len(value_str)
            end_ind = html_text.find('">')
            try:
                salary_value = int(html_text[start_ind:end_ind])
            except:
                salary_value = 0
            player_list.append(salary_value)
            html_text = html_text[end_ind + 2:]

        player_list.append(play_key)
        player_salaries[player_key] = {}
        player_salaries[player_key]['salary'] = player_list

        total_val = html_text.find('class="name">Totals	')
        url_val = html_text.find('<a')

    return player_salaries

def get_player_salary(team_url):
    """ This function pulls player salary information for six seasons
    from `hoopshype.com <https://hoopshype.com/salaries/>`

    @param team_url (str): String of URL corresponding
    to a single team's salary

    Returns:

        **player_salaries** (*dict*): Dictionary keyed by Hoopshype
            player ID with a list of yearly salaries as values

        **column_list** (*list*): List of column names for team
            salary information
    """

    api_resp = get(team_url)
    html_text = api_resp.text
    sorted_str = 'hh-salaries-sorted'

    table_index = html_text.find(sorted_str)
    html_text = html_text[table_index:]
    html_text, column_list = salary_columns(html_text)
    column_list.append('url')

    player_salaries = player_salary_values(html_text)

    return player_salaries, column_list

def get_historical_player_salary(team_url, season):
    """ This function pulls historical player salary information for six seasons
    from `hoopshype.com <https://hoopshype.com/salaries/>`

    @param **team_url** (*str*): Hoopshype URL beginning with SALARY_URL
        appended with a season value. For example,
        'http://example.com/' is a valid
        **team_url**

    @param **season** (*str*): Season in YYYY-ZZZZ format. For example,
        '2017-2018' corresponds to the 2017-2018 NBA season
    Returns:

        **player_salaries** (*dict*): Dictionary keyed by Hoopshype
            player ID with a list of yearly salaries as values

        **column_list** (*list*): List of column names for team
            salary information
    """

    api_resp = get(team_url)
    html_text = api_resp.text
    sorted_str = 'class="name">Player	'

    table_index = html_text.find(sorted_str) + len(sorted_str)
    html_text = html_text[table_index:]
    html_text, column_list = salary_columns(html_text, season)
    column_list.append('url')

    player_salaries = historical_player_salary_values(html_text)

    return player_salaries, column_list

class TeamSalaries:
    """ The TeamSalaries class contains all resources needed
    to scrape team salary information from
    `hoopshype.com <https://hoopshype.com/salaries/>`.
    This class contains both team total salary as well as individual
    player breakdowns

    Attributes:

        **totals** (*dict*): Dictionary keyed by NBA
            team ID with a list of yearly salaries (followed
            by team salary URL) as values

        **totals_columns** (*list*): List of column names for team
            salary information

        **team_player_salaries** (*dict*): Dictionary keyed by both NBA
            team ID and Hoopshype player ID with values containing both
            salary and option information

        **team_player_columns** (*list*): List of column names for team-player
            salary information
    """

    def __init__(self):

        # First, total team salary information is pulled
        team_salaries, column_list = get_team_salary()
        self.totals = team_salaries
        self.totals_columns = column_list
        team_player_salary = {}
        for team_id in team_salaries:
            team_url = team_salaries[team_id][-1]
            player_salaries, column_list = get_player_salary(team_url)
            team_player_salary[team_id] = player_salaries

        self.team_player_salaries = team_player_salary
        self.team_player_columns = column_list

class HistoricalSalaries:
    """ The HistoricalSalaries class contains all resources needed
    to scrape team salary information from
    `hoopshype.com <https://hoopshype.com/salaries/>` for a given season.
    This class contains both team total salary as well as individual
    player breakdowns

    @param **season** (*str*): String of season in YYYY-ZZZZ
    format

    Attributes:

        **totals** (*dict*): Dictionary keyed by NBA
            team ID with a list of salaries and inflation-adjusted salaries
            (followed by team salary URL) as values

        **totals_columns** (*list*): List of column names for historical team
            salary information

        **team_player_salaries** (*dict*): Dictionary keyed by both NBA
            team ID and Hoopshype player ID with values containing
            salary information

        **team_player_columns** (*list*): List of column names for historical
            team-player salary information
    """

    def __init__(self, season='2017-2018'):

        # First, total team salary information is pulled
        team_salaries, column_list = get_historical_team_salary(season)
        self.totals = team_salaries
        self.totals_columns = column_list
        team_player_salary = {}
        for team_id in team_salaries:
            team_url = team_salaries[team_id][-1]
            player_salaries, column_list = get_historical_player_salary(team_url, season)
            team_player_salary[team_id] = player_salaries

        self.team_player_salaries = team_player_salary
        self.team_player_columns = column_list