/*
 *
 * 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.
 *
 */

/* eslint-disable standard/no-callback-literal */
/* global Windows, setImmediate */

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);
