/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

/* jslint sloppy:true */
/* global Windows:true, setImmediate */
/* eslint standard/no-callback-literal : 0 */

var cordova = require('cordova');
var urlutil = require('cordova/urlutil');

var browserWrap,
    popup,
    navigationButtonsDiv,
    navigationButtonsDivInner,
    backButton,
    forwardButton,
    closeButton,
    bodyOverflowStyle,
    navigationEventsCallback,
    hardwareBackCallback;

// x-ms-webview is available starting from Windows 8.1 (platformId is 'windows')
// http://msdn.microsoft.com/en-us/library/windows/apps/dn301831.aspx
var isWebViewAvailable = cordova.platformId === 'windows';

function attachNavigationEvents (element, callback) {
    if (isWebViewAvailable) {
        element.addEventListener('MSWebViewNavigationStarting', function (e) {
            callback({ type: 'loadstart', url: e.uri }, {keepCallback: true});
        });

        element.addEventListener('MSWebViewNavigationCompleted', function (e) {
            if (e.isSuccess) {
                callback({ type: 'loadstop', url: e.uri }, { keepCallback: true });
            } else {
                callback({ type: 'loaderror', url: e.uri, code: e.webErrorStatus, message: 'Navigation failed with error code ' + e.webErrorStatus }, { keepCallback: true });
            }
        });

        element.addEventListener('MSWebViewUnviewableContentIdentified', function (e) {
            // WebView found the content to be not HTML.
            // http://msdn.microsoft.com/en-us/library/windows/apps/dn609716.aspx
            callback({ type: 'loaderror', url: e.uri, code: e.webErrorStatus, message: 'Navigation failed with error code ' + e.webErrorStatus }, { keepCallback: true });
        });

        element.addEventListener('MSWebViewContentLoading', function (e) {
            if (navigationButtonsDiv && popup) {
                if (popup.canGoBack) {
                    backButton.removeAttribute('disabled');
                } else {
                    backButton.setAttribute('disabled', 'true');
                }

                if (popup.canGoForward) {
                    forwardButton.removeAttribute('disabled');
                } else {
                    forwardButton.setAttribute('disabled', 'true');
                }
            }
        });
    } else {
        var onError = function () {
            callback({ type: 'loaderror', url: this.contentWindow.location }, {keepCallback: true});
        };

        element.addEventListener('unload', function () {
            callback({ type: 'loadstart', url: this.contentWindow.location }, {keepCallback: true});
        });

        element.addEventListener('load', function () {
            callback({ type: 'loadstop', url: this.contentWindow.location }, {keepCallback: true});
        });

        element.addEventListener('error', onError);
        element.addEventListener('abort', onError);
    }
}

var IAB = {
    close: function (win, lose) {
        setImmediate(function () {
            if (browserWrap) {
                if (navigationEventsCallback) {
                    navigationEventsCallback({ type: 'exit' });
                }

                browserWrap.parentNode.removeChild(browserWrap);
                // Reset body overflow style to initial value
                document.body.style.msOverflowStyle = bodyOverflowStyle;
                browserWrap = null;
                popup = null;

                document.removeEventListener('backbutton', hardwareBackCallback, false);
            }
        });
    },
    show: function (win, lose) {
        setImmediate(function () {
            if (browserWrap) {
                browserWrap.style.display = 'block';
            }
        });
    },
    hide: function (win, lose) {
        if (browserWrap) {
            browserWrap.style.display = 'none';
        }
    },
    open: function (win, lose, args) {
        // make function async so that we can add navigation events handlers before view is loaded and navigation occured
        setImmediate(function () {
            var strUrl = args[0];
            var target = args[1];
            var features = args[2];
            var url;

            navigationEventsCallback = win;

            if (target === '_system') {
                url = new Windows.Foundation.Uri(strUrl);
                Windows.System.Launcher.launchUriAsync(url);
            } else if (target === '_self' || !target) {
                window.location = strUrl;
            } else {
                // "_blank" or anything else
                if (!browserWrap) {
                    var browserWrapStyle = document.createElement('link');
                    browserWrapStyle.rel = 'stylesheet';
                    browserWrapStyle.type = 'text/css';
                    browserWrapStyle.href = urlutil.makeAbsolute('/www/css/inappbrowser.css');

                    document.head.appendChild(browserWrapStyle);

                    browserWrap = document.createElement('div');
                    browserWrap.className = 'inAppBrowserWrap';

                    if (features.indexOf('fullscreen=yes') > -1) {
                        browserWrap.classList.add('inAppBrowserWrapFullscreen');
                    }

                    // Save body overflow style to be able to reset it back later
                    bodyOverflowStyle = document.body.style.msOverflowStyle;

                    browserWrap.onclick = function () {
                        setTimeout(function () {
                            IAB.close(navigationEventsCallback);
                        }, 0);
                    };

                    document.body.appendChild(browserWrap);
                    // Hide scrollbars for the whole body while inappbrowser's window is open
                    document.body.style.msOverflowStyle = 'none';
                }

                if (features.indexOf('hidden=yes') !== -1) {
                    browserWrap.style.display = 'none';
                }

                popup = document.createElement(isWebViewAvailable ? 'x-ms-webview' : 'iframe');
                if (popup instanceof HTMLIFrameElement) { // eslint-disable-line no-undef
                    // For iframe we need to override bacground color of parent element here
                    // otherwise pages without background color set will have transparent background
                    popup.style.backgroundColor = 'white';
                }
                popup.style.borderWidth = '0px';
                popup.style.width = '100%';
                popup.style.marginBottom = '-5px';

                browserWrap.appendChild(popup);

                var closeHandler = function (e) {
                    setTimeout(function () {
                        IAB.close(navigationEventsCallback);
                    }, 0);
                };

                if (features.indexOf('hardwareback=yes') > -1 || features.indexOf('hardwareback') === -1) {
                    hardwareBackCallback = function () {
                        if (browserWrap.style.display === 'none') {
                            // NOTE: backbutton handlers have to throw an exception in order to prevent
                            // returning 'true' inside cordova-js, which would mean that the event is handled by user.
                            // Throwing an exception means that the default/system navigation behavior will take place,
                            // which is to exit the app if the navigation stack is empty.
                            throw 'Exit the app'; // eslint-disable-line no-throw-literal
                        }

                        if (popup.canGoBack) {
                            popup.goBack();
                        } else {
                            closeHandler();
                        }
                    };
                } else if (features.indexOf('hardwareback=no') > -1) {
                    hardwareBackCallback = function () {
                        if (browserWrap.style.display === 'none') {
                            // See comment above
                            throw 'Exit the app'; // eslint-disable-line no-throw-literal
                        }

                        closeHandler();
                    };
                }

                document.addEventListener('backbutton', hardwareBackCallback, false);

                if (features.indexOf('location=yes') !== -1 || features.indexOf('location') === -1) {
                    popup.style.height = 'calc(100% - 70px)';

                    navigationButtonsDiv = document.createElement('div');
                    navigationButtonsDiv.className = 'inappbrowser-app-bar';
                    navigationButtonsDiv.onclick = function (e) {
                        e.cancelBubble = true;
                    };

                    navigationButtonsDivInner = document.createElement('div');
                    navigationButtonsDivInner.className = 'inappbrowser-app-bar-inner';
                    navigationButtonsDivInner.onclick = function (e) {
                        e.cancelBubble = true;
                    };

                    backButton = document.createElement('div');
                    backButton.innerText = 'back';
                    backButton.className = 'app-bar-action action-back';
                    backButton.addEventListener('click', function (e) {
                        if (popup.canGoBack) { popup.goBack(); }
                    });

                    forwardButton = document.createElement('div');
                    forwardButton.innerText = 'forward';
                    forwardButton.className = 'app-bar-action action-forward';
                    forwardButton.addEventListener('click', function (e) {
                        if (popup.canGoForward) { popup.goForward(); }
                    });

                    closeButton = document.createElement('div');
                    closeButton.innerText = 'close';
                    closeButton.className = 'app-bar-action action-close';
                    closeButton.addEventListener('click', closeHandler);

                    if (!isWebViewAvailable) {
                        // iframe navigation is not yet supported
                        backButton.setAttribute('disabled', 'true');
                        forwardButton.setAttribute('disabled', 'true');
                    }

                    navigationButtonsDivInner.appendChild(backButton);
                    navigationButtonsDivInner.appendChild(forwardButton);
                    navigationButtonsDivInner.appendChild(closeButton);
                    navigationButtonsDiv.appendChild(navigationButtonsDivInner);

                    browserWrap.appendChild(navigationButtonsDiv);
                } else {
                    popup.style.height = '100%';
                }

                // start listening for navigation events
                attachNavigationEvents(popup, navigationEventsCallback);

                if (isWebViewAvailable) {
                    strUrl = strUrl.replace('ms-appx://', 'ms-appx-web://');
                }
                popup.src = strUrl;
            }
        });
    },

    injectScriptCode: function (win, fail, args) {
        setImmediate(function () {
            var code = args[0];
            var hasCallback = args[1];

            if (isWebViewAvailable && browserWrap && popup) {
                var op = popup.invokeScriptAsync('eval', code);
                op.oncomplete = function (e) {
                    if (hasCallback) {
                        // return null if event target is unavailable by some reason
                        var result = (e && e.target) ? [e.target.result] : [null];
                        win(result);
                    }
                };
                op.onerror = function () { };
                op.start();
            }
        });
    },

    injectScriptFile: function (win, fail, args) {
        setImmediate(function () {
            var filePath = args[0];
            var hasCallback = args[1];

            if (filePath) {
                filePath = urlutil.makeAbsolute(filePath);
            }

            if (isWebViewAvailable && browserWrap && popup) {
                // CB-12364 getFileFromApplicationUriAsync does not support ms-appx-web
                var uri = new Windows.Foundation.Uri(filePath.replace('ms-appx-web:', 'ms-appx:'));
                Windows.Storage.StorageFile.getFileFromApplicationUriAsync(uri).done(function (file) {
                    Windows.Storage.FileIO.readTextAsync(file).done(function (code) {
                        var op = popup.invokeScriptAsync('eval', code);
                        op.oncomplete = function (e) {
                            if (hasCallback) {
                                var result = [e.target.result];
                                win(result);
                            }
                        };
                        op.onerror = function () { };
                        op.start();
                    });
                });
            }
        });
    },

    injectStyleCode: function (win, fail, args) {
        setImmediate(function () {
            var code = args[0];
            var hasCallback = args[1];

            if (isWebViewAvailable && browserWrap && popup) {
                injectCSS(popup, code, hasCallback && win);
            }
        });
    },

    injectStyleFile: function (win, fail, args) {
        setImmediate(function () {
            var filePath = args[0];
            var hasCallback = args[1];

            filePath = filePath && urlutil.makeAbsolute(filePath);

            if (isWebViewAvailable && browserWrap && popup) {
                // CB-12364 getFileFromApplicationUriAsync does not support ms-appx-web
                var uri = new Windows.Foundation.Uri(filePath.replace('ms-appx-web:', 'ms-appx:'));
                Windows.Storage.StorageFile.getFileFromApplicationUriAsync(uri).then(function (file) {
                    return Windows.Storage.FileIO.readTextAsync(file);
                }).done(function (code) {
                    injectCSS(popup, code, hasCallback && win);
                }, function () {
                    // no-op, just catch an error
                });
            }
        });
    }
};

function injectCSS (webView, cssCode, callback) {
    // This will automatically escape all thing that we need (quotes, slashes, etc.)
    var escapedCode = JSON.stringify(cssCode);
    var evalWrapper = '(function(d){var c=d.createElement(\'style\');c.innerHTML=%s;d.head.appendChild(c);})(document)'
        .replace('%s', escapedCode);

    var op = webView.invokeScriptAsync('eval', evalWrapper);
    op.oncomplete = function () {
        if (callback) {
            callback([]);
        }
    };
    op.onerror = function () { };
    op.start();
}

module.exports = IAB;

require('cordova/exec/proxy').add('InAppBrowser', module.exports);
