/**
 * DevExtreme (ui/scroll_view/ui.scroll_view.js)
 * Version: 17.2.8 (build 18184)
 * Build date: Tue Jul 03 2018
 *
 * Copyright (c) 2012 - 2018 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
"use strict";
var $ = require("../../core/renderer"),
    devices = require("../../core/devices"),
    messageLocalization = require("../../localization/message"),
    registerComponent = require("../../core/component_registrator"),
    extend = require("../../core/utils/extend").extend,
    PullDownStrategy = require("./ui.scroll_view.native.pull_down"),
    SwipeDownStrategy = require("./ui.scroll_view.native.swipe_down"),
    SlideDownStrategy = require("./ui.scroll_view.native.slide_down"),
    SimulatedStrategy = require("./ui.scroll_view.simulated"),
    Scrollable = require("./ui.scrollable"),
    LoadIndicator = require("../load_indicator"),
    config = require("../../core/config"),
    LoadPanel = require("../load_panel");
var SCROLLVIEW_CLASS = "dx-scrollview",
    SCROLLVIEW_CONTENT_CLASS = SCROLLVIEW_CLASS + "-content",
    SCROLLVIEW_TOP_POCKET_CLASS = SCROLLVIEW_CLASS + "-top-pocket",
    SCROLLVIEW_BOTTOM_POCKET_CLASS = SCROLLVIEW_CLASS + "-bottom-pocket",
    SCROLLVIEW_PULLDOWN_CLASS = SCROLLVIEW_CLASS + "-pull-down",
    SCROLLVIEW_REACHBOTTOM_CLASS = SCROLLVIEW_CLASS + "-scrollbottom",
    SCROLLVIEW_REACHBOTTOM_INDICATOR_CLASS = SCROLLVIEW_REACHBOTTOM_CLASS + "-indicator",
    SCROLLVIEW_REACHBOTTOM_TEXT_CLASS = SCROLLVIEW_REACHBOTTOM_CLASS + "-text",
    SCROLLVIEW_LOADPANEL = SCROLLVIEW_CLASS + "-loadpanel";
var refreshStrategies = {
    pullDown: PullDownStrategy,
    swipeDown: SwipeDownStrategy,
    slideDown: SlideDownStrategy,
    simulated: SimulatedStrategy
};
var ScrollView = Scrollable.inherit({
    _getDefaultOptions: function() {
        return extend(this.callBase(), {
            pullingDownText: messageLocalization.format("dxScrollView-pullingDownText"),
            pulledDownText: messageLocalization.format("dxScrollView-pulledDownText"),
            refreshingText: messageLocalization.format("dxScrollView-refreshingText"),
            reachBottomText: messageLocalization.format("dxScrollView-reachBottomText"),
            onPullDown: null,
            onReachBottom: null,
            refreshStrategy: "pullDown"
        })
    },
    _defaultOptionsRules: function() {
        return this.callBase().concat([{
            device: function() {
                var realDevice = devices.real();
                return "android" === realDevice.platform
            },
            options: {
                refreshStrategy: "swipeDown"
            }
        }, {
            device: function() {
                return "win" === devices.real().platform
            },
            options: {
                refreshStrategy: "slideDown"
            }
        }])
    },
    _init: function() {
        this.callBase();
        this._loadingIndicatorEnabled = true
    },
    _initMarkup: function() {
        this.callBase();
        this.$element().addClass(SCROLLVIEW_CLASS);
        this._initContent();
        this._initTopPocket();
        this._initBottomPocket();
        this._initLoadPanel()
    },
    _initContent: function() {
        var $content = $("<div>").addClass(SCROLLVIEW_CONTENT_CLASS);
        this._$content.wrapInner($content)
    },
    _initTopPocket: function() {
        var $topPocket = this._$topPocket = $("<div>").addClass(SCROLLVIEW_TOP_POCKET_CLASS),
            $pullDown = this._$pullDown = $("<div>").addClass(SCROLLVIEW_PULLDOWN_CLASS);
        $topPocket.append($pullDown);
        this._$content.prepend($topPocket)
    },
    _initBottomPocket: function() {
        var $bottomPocket = this._$bottomPocket = $("<div>").addClass(SCROLLVIEW_BOTTOM_POCKET_CLASS),
            $reachBottom = this._$reachBottom = $("<div>").addClass(SCROLLVIEW_REACHBOTTOM_CLASS),
            $loadContainer = $("<div>").addClass(SCROLLVIEW_REACHBOTTOM_INDICATOR_CLASS),
            $loadIndicator = new LoadIndicator($("<div>")).$element(),
            $text = this._$reachBottomText = $("<div>").addClass(SCROLLVIEW_REACHBOTTOM_TEXT_CLASS);
        this._updateReachBottomText();
        $reachBottom.append($loadContainer.append($loadIndicator)).append($text);
        $bottomPocket.append($reachBottom);
        this._$content.append($bottomPocket)
    },
    _initLoadPanel: function() {
        this._loadPanel = this._createComponent($("<div>").addClass(SCROLLVIEW_LOADPANEL).appendTo(this.$element()), LoadPanel, {
            shading: false,
            delay: 400,
            message: this.option("refreshingText"),
            position: { of: this.$element()
            }
        })
    },
    _updateReachBottomText: function() {
        this._$reachBottomText.text(this.option("reachBottomText"))
    },
    _createStrategy: function() {
        var strategyName = this.option("useNative") ? this.option("refreshStrategy") : "simulated";
        var strategyClass = refreshStrategies[strategyName];
        if (!strategyClass) {
            throw Error("E1030", this.option("refreshStrategy"))
        }
        this._strategy = new strategyClass(this);
        this._strategy.pullDownCallbacks.add(this._pullDownHandler.bind(this));
        this._strategy.releaseCallbacks.add(this._releaseHandler.bind(this));
        this._strategy.reachBottomCallbacks.add(this._reachBottomHandler.bind(this))
    },
    _createActions: function() {
        this.callBase();
        this._pullDownAction = this._createActionByOption("onPullDown");
        this._reachBottomAction = this._createActionByOption("onReachBottom");
        this._refreshPocketState()
    },
    _refreshPocketState: function() {
        this._pullDownEnable(this.hasActionSubscription("onPullDown") && !config().designMode);
        this._reachBottomEnable(this.hasActionSubscription("onReachBottom") && !config().designMode)
    },
    on: function(eventName) {
        var result = this.callBase.apply(this, arguments);
        if ("pullDown" === eventName || "reachBottom" === eventName) {
            this._refreshPocketState()
        }
        return result
    },
    _pullDownEnable: function(enabled) {
        if (0 === arguments.length) {
            return this._pullDownEnabled
        }
        this._$pullDown.toggle(enabled);
        this._strategy.pullDownEnable(enabled);
        this._pullDownEnabled = enabled
    },
    _reachBottomEnable: function(enabled) {
        if (0 === arguments.length) {
            return this._reachBottomEnabled
        }
        this._$reachBottom.toggle(enabled);
        this._strategy.reachBottomEnable(enabled);
        this._reachBottomEnabled = enabled
    },
    _pullDownHandler: function() {
        this._loadingIndicator(false);
        this._pullDownLoading()
    },
    _loadingIndicator: function(value) {
        if (arguments.length < 1) {
            return this._loadingIndicatorEnabled
        }
        this._loadingIndicatorEnabled = value
    },
    _pullDownLoading: function() {
        this.startLoading();
        this._pullDownAction()
    },
    _reachBottomHandler: function() {
        this._loadingIndicator(false);
        this._reachBottomLoading()
    },
    _reachBottomLoading: function() {
        this.startLoading();
        this._reachBottomAction()
    },
    _releaseHandler: function() {
        this.finishLoading();
        this._loadingIndicator(true)
    },
    _optionChanged: function(args) {
        switch (args.name) {
            case "onPullDown":
            case "onReachBottom":
                this._createActions();
                break;
            case "pullingDownText":
            case "pulledDownText":
            case "refreshingText":
            case "refreshStrategy":
                this._invalidate();
                break;
            case "reachBottomText":
                this._updateReachBottomText();
                break;
            default:
                this.callBase(args)
        }
    },
    isEmpty: function() {
        return !this.content().children().length
    },
    content: function() {
        return this._$content.children().eq(1)
    },
    release: function(preventReachBottom) {
        if (void 0 !== preventReachBottom) {
            this.toggleLoading(!preventReachBottom)
        }
        return this._strategy.release()
    },
    toggleLoading: function(showOrHide) {
        this._reachBottomEnable(showOrHide)
    },
    isFull: function() {
        return this.content().height() > this._$container.height()
    },
    refresh: function() {
        if (!this.hasActionSubscription("onPullDown")) {
            return
        }
        this._strategy.pendingRelease();
        this._pullDownLoading()
    },
    startLoading: function() {
        if (this._loadingIndicator() && this.$element().is(":visible")) {
            this._loadPanel.show()
        }
        this._lock()
    },
    finishLoading: function() {
        this._loadPanel.hide();
        this._unlock()
    },
    _dispose: function() {
        this._strategy.dispose();
        this.callBase();
        if (this._loadPanel) {
            this._loadPanel.$element().remove()
        }
    }
});
registerComponent("dxScrollView", ScrollView);
module.exports = ScrollView;
