#!/usr/bin/env python
"""This file handles parsing the Wix Instance to verify that the Instance did
indeed come from Wix.

Functions are provided to get the instance ID from a Wix Instance and to check
if the owner of the app made the request that the Wix Instance came with.

See Wix's documentation to get more information on the Wix Instance and
the properties of the parsed Wix Instance.
http://dev.wix.com/docs/display/DRAF/Using+the+Signed+App+Instance
"""

from base64 import urlsafe_b64encode, urlsafe_b64decode
from hmac import new
from hashlib import sha256
from json import loads

__author__ = "Jeffrey Chan"
__version__ = "2.0.3"


def get_instance_ID(wix_secret, instance, check_owner=False):
    """This function parses the Wix instance and then returns the instance ID
    from the parsed instance as a Unicode string.

    If check_owner is true, it also verifies that the instance was generated by
    the owner of the app. Use this to verify requests that only the owner of
    the app should be able to make (e.g. Changes in the app settings).

    If anything goes wrong (e.g. the instance is invalid), the function returns
    false.
    """
    parsed_instance = instance_parser(wix_secret, instance)
    if parsed_instance:
        if check_owner:
            if parsed_instance["permissions"] == "OWNER":
                return parsed_instance["instanceId"]
            else:
                return False
        else:
            return parsed_instance["instanceId"]
    else:
        return False


def instance_parser(wix_secret, instance):
    """This function parses the Wix instance that comes with every call to the
    server. If the parse is successful (the instance is from Wix and the
    permission is set to owner), the call is from a valid source and
    the request it came with should be performed. The function returns the
    parsed instance on success and false otherwise.

    This function should only be called if you want the entire parsed instance
    object rather than just the instance ID.
    """
    try:
        signature, encoded_json = instance.split(".", 2)
        encoded_json_with_padding = (encoded_json +
                                     ('=' * (4 - (len(encoded_json) % 4))))
        parsed_instance = urlsafe_b64decode(
            encoded_json_with_padding.encode("utf-8"))
        hmac_hashed = new(wix_secret.encode("utf-8"), msg=encoded_json.encode("utf-8"),
                          digestmod=sha256).digest()
        new_signature_bytes = urlsafe_b64encode(hmac_hashed)
        new_signature_str = new_signature_bytes.decode("utf-8")
        new_signature = new_signature_str.replace("=", "")
        if (new_signature == signature):
            return loads(parsed_instance.decode("utf-8"))
        else:
            return False
    except Exception:
        return False
