DirectedEdgeDynamicCart = {
    endpoints: ["/cart/change.js", "/cart/add.js", "/cart/update.js",
                "/cart/clear.js" ]
};
  
DirectedEdgeDynamicCart.ajax = function(method, url, params, success, error)
{
    var request;

    if(window.XMLHttpRequest)
    {
        request = new XMLHttpRequest();
    }
    else if(window.ActiveXObject)
    {
        request = new ActiveXObject("Microsoft.XMLHTTP");
    }
    else
    {
        throw "Could not create AJAX request.";
    }

    request.open(method, url, true);
    request.setRequestHeader("Accept", "application/json, text/javascript, */*");
    request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    request.onreadystatechange = function (e) {
        if(request.readyState == 4)
        {
            if(request.status == 200)
            {
                success(e.target.responseText);
            }
            else
            {
                if(error != undefined)
                {
                    error(e);
                }
            }
        }
    };

    request.send(params);
};

DirectedEdgeDynamicCart.addAjaxHandler = function(handler)
{
    var ajaxProto;

    if(window.XMLHttpRequest)
    {
        ajaxProto = XMLHttpRequest.prototype;
    }
    else if(window.ActiveXObject)
    {
        ajaxProto = ActiveXObject("Microsoft.XMLHTTP").prototype;
    }

    var openOriginial = ajaxProto.open;
    ajaxProto.open = function() {
        this.addEventListener("load", function(event) {
            var url = event.srcElement._url;

            if(event.srcElement.readyState == 4 &&
               DirectedEdgeDynamicCart.matchesEndpoint(url, event.srcElement._method))
            {
                handler();
            }
        }, false);

        return openOriginial.apply(this, arguments);
    };

    var fetchOriginal = window.fetch;
    window.fetch = function() {
        var url = arguments[0];
        if(arguments.length < 2)
        {
            return fetchOriginal.apply(this, arguments);
        }

        var object = arguments[1];
        if(DirectedEdgeDynamicCart.matchesEndpoint(url, object.method))
        {
            var fetchArgs = arguments;
            return new Promise(function(resolve, reject) {
                fetchOriginal.apply(this, fetchArgs).then(function(response) {
                    handler();
                    resolve(response);
                }).catch(function(error) {
                    reject(error);
                });
            });
        }

        return fetchOriginal.apply(this, arguments);
    }
};

DirectedEdgeDynamicCart.getCartList = function(callback)
{
    DirectedEdgeDynamicCart.ajax("GET", "/cart.js", "", function(data) {
        var productIds = [];
        var cart = JSON.parse(data);
        var count = cart.items.length;
        for(var i = 0; i < count; i++)
        {
            productIds.push(cart.items[i].product_id);
        }

        if(callback != undefined)
        {
            callback(productIds.join(","), true, cart.token);
        }
    }, function(event) {
        if(callback != undefined)
        {
            callback(null, false);
        }
    });
}

DirectedEdgeDynamicCart.submitCart = function(callback)
{
    DirectedEdgeDynamicCart.getCartList(function(list, success) {
        if(success)
        {
            var request = "shop=" + Shopify.shop + "&cart=" + list;
            DirectedEdgeDynamicCart.ajax("POST", "//app.directededge.com/basket/update", request,
                                         function() {
                                             if(callback != undefined)
                                             {
                                                 callback(true);
                                             }
                                         }, function() {
                                             if(callback != undefined)
                                             {
                                                 callback(false);
                                             }
                                         });
        }
        else
        {
            if(callback != undefined)
            {
                callback(false);
            }
        }
    });
};

DirectedEdgeDynamicCart.matchesEndpoint = function(url, method)
{
    for(var i = 0; i < DirectedEdgeDynamicCart.endpoints.length; i++)
    {
        var endpoint = DirectedEdgeDynamicCart.endpoints[i];
        if(url.indexOf(endpoint) == 0)
        {
            if(method == "POST" || url.indexOf("&") != -1)
            {
                return true;
            }
        }
    }

    return false;
};

function DirectedEdgeQuery(domain, parameters)
{
    this.domain = domain;
    this.parameters = parameters;
}

DirectedEdgeQuery.prototype.formatQuery = function()
{
    var url = window.location.protocol +
              "//app.directededge.com/widget?shop=" + this.domain;
    for(var p in this.parameters)
    {
        url += "&" + p + "=" + encodeURIComponent(this.parameters[p]);
    }

    return url;
};

DirectedEdgeQuery.prototype.generateGUID = function()
{
    return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
        var r = Math.random() * 16 | 0;
        var v = c == "x" ? r : r & 0x3 | 0x8;
        return v.toString(16);
    });
};

DirectedEdgeQuery.prototype.checkGUIDCookie = function()
{
    var guid = this.getCookie("de_guid");

    if(!guid)
    {
        guid = this.generateGUID();

        var expires = new Date();
        expires.setFullYear(expires.getFullYear() + 2);

        this.setCookie("de_guid", guid, expires);
    }

    return guid;
};

DirectedEdgeQuery.prototype.setBridgeCookie = function()
{
    var expires = new Date();
    expires.setHours(expires.getHours() + 48);

    var val = DirectedEdgeBrowserId.generate(this.basket);
    this.setCookie("de_bridge", val, expires);
};

DirectedEdgeQuery.prototype.getCookie = function(key)
{
    var cookies = new Object();
    var pairs = document.cookie.split("; ");
    for(var i = 0; i < pairs.length; i++)
    {
        var pair = pairs[i].split("=");
        if(pair[0] === key)
        {
            return pair[1];
        }
    }

    return undefined;
};

DirectedEdgeQuery.prototype.setCookie = function(key, value, expires)
{
    document.cookie =
        key + "=" + value + "; " +
        "expires=" + expires.toUTCString() + "; " +
        "path=/";
};

DirectedEdgeQuery.prototype.handleCartChange = function()
{
    var thisQuery = this;
    DirectedEdgeDynamicCart.getCartList(function(list, success) {
        if(success)
        {
            var params = thisQuery.parameters;
            params.basket = list;
            params.insert = "replace";
            var q = new DirectedEdgeQuery(Shopify.shop, params);
            var deDiv = document.getElementById(params.block_id);
            q.execute();
        }
    });
}

DirectedEdgeQuery.prototype.execute = function()
{
    this.parameters["tracking"] = this.checkGUIDCookie();

    var script = document.createElement("script");
    script.setAttribute("type", "text/javascript");
    script.setAttribute("charset", "utf-8");
    script.setAttribute("src", this.formatQuery());
    document.getElementsByTagName("head").item(0).appendChild(script);
};

DirectedEdgeQuery.prototype.executeAsync = function()
{
    var query = this;
    setTimeout(function() { query.execute(); }, 0);
};


DirectedEdgeObserver = {
    selector: "",
    placement: "after",
    timer: null,
    scope: 0
};

DirectedEdgeObserver.domChange = function(mutations, observer)
{
    var additions = 0;

    for(var i = 0; i < mutations.length; i++)
    {
        var mutation = mutations[i];
        additions += mutation.addedNodes.length;
    }

    if(additions == 0)
    {
        return;
    }

    if(DirectedEdgeObserver.timer)
    {
        clearTimeout(DirectedEdgeObserver.timer);
    }

    DirectedEdgeObserver.timer = setTimeout(function() {
       DirectedEdgeObserver.process(observer);
    }, 50);
}

DirectedEdgeObserver.process = function()
{
    clearTimeout(DirectedEdgeObserver.timer);
    DirectedEdgeObserver.timer = null;

    var items = document.getElementsByClassName("directededge-mini-cart");

    if(items.length == 0)
    {
        if(DirectedEdgeObserver.selector.length > 0)
        {
            var matched = document.querySelectorAll(DirectedEdgeObserver.selector);
            if(matched.length > 0)
            {
                var selected = matched[matched.length - 1];
                var item = document.createElement("div");
                item.className = "directededge-mini-cart";
                var position = DirectedEdgeObserver.placement == "before"
                    ? "beforebegin" : "afterend";
                selected.insertAdjacentElement(position, item);
                items = [item];
            }
        }
    }

    for(var j = 0; j < items.length; j++)
    {
        var de = items[j];

        var classes = de.className.split(" ");
        for(classIndex = 0; classIndex < classes.length; classIndex++)
        {
            if(classes[classIndex] == "directededge-expanded")
            {
                return;
            }
        }

        if(de.attributes["id"] == undefined)
        {
            de.setAttribute("id", "directededge-blocks-mini-cart");
        }

        de.className += " directededge-expanded";

        DirectedEdgeDynamicCart.getCartList(function(items, success, cartToken) {
            var parameters = { "block_id": de.attributes["id"].value,
                               "template": "mini-cart",
                               "cart_token": cartToken,
                               "basket": items,
                               "currency_code": Shopify.currency.active,
                               "currency_rate": Shopify.currency.rate,
                               "insert": "replace"
            };

            var query = new DirectedEdgeQuery(Shopify.shop, parameters);
            query.parameters["bridge"] = query.getCookie("de_bridge");
            DirectedEdgeDynamicCart.addAjaxHandler(function() {
                query.handleCartChange();
            });

            query.execute();
        });
    }
};

(function() {
    var MutationObserver = window.MutationObserver
                        || window.WebKitMutationObserver
                        || window.MozMutationObserver;

    if(MutationObserver)
    {
        var observer = new MutationObserver(DirectedEdgeObserver.domChange);
        observer.observe(document.documentElement, {
            attributes: false,
            characterData: false,
            childList: true,
            subtree: true,
            attributeOldValue: false,
            characterDataOldValue: false
        });

        DirectedEdgeObserver.process();
    }
})();
