/*
 * 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.
*/
define([
    "jquery", "underscore", "backbone", "moment", "view/viewutils",
    "model/server-extended-status",
    "text!tpl/home/ha-summary.html"
], function ($, _, Backbone, moment, ViewUtils, serverStatus, HASummaryHtml) {

    var template = _.template(HASummaryHtml);
    var nodeRowTemplate = _.template(
        "<tr>" +
            "<td>" +
                "<% if (nodeUri && !isTerminated) { %><a href='<%= nodeUri %>'><%= nodeId %></a><% } else { %><%= nodeId %><%    } %>" +
                "<% if (isSelf) { %><span class='pull-right badge badge-success'>this</span><% } %>" +
            "</td>" +
            "<td><% if (isPretendMaster) {%>EX-MASTER<%} else {%><%= status %><%} if (isStale) { %> (stale)<% } %></td>" +
            "<td><%= timestampDisplayPrefix %><span class='timestamp' data-timestamp='<%= timestamp %>'><%= timestampDisplay %><span><%= timestampDisplaySuffix %></td>" +
        "</tr>");
    var noServers = "<tr><td colspan='3'><i>Failed to load data of servers</i></td></tr>";
    var waitingServers = "<tr><td colspan='3'><i>Waiting on detail for servers...</i></td></tr>";

    var HASummaryView = Backbone.View.extend({
        initialize: function() {
            _.bindAll(this);
            this.updateTimestampCallback = setInterval(this.updateTimestamps, 1000);
            this.listenTo(serverStatus, "change", this.renderNodeStatus);
        },
        beforeClose: function() {
            clearInterval(this.updateTimestampCallback);
            this.stopListening();
        },
        updateNow: function() {
            serverStatus.fetch();
        },
        render: function() {
            this.$el.html(template());
            this.renderNodeStatus();
            return this;
        },
        renderNodeStatus: function() {
            var $target = this.$(".ha-summary-table-body");
            if (!serverStatus.loaded) {
                $target.html(waitingServers);
                return;
            }
            
            var serverHa = serverStatus.get("ha") || {};
            var master = serverHa.masterId,
                self = serverHa.ownId,
                nodes = serverHa.nodes;
                
            // undefined check just in case server returns something odd
            if (nodes == undefined || _.isEmpty(nodes)) {
                $target.html(noServers);
                return;
            }
            
            $target.empty();
            var masterTimestamp;
            _.each(nodes, function (n) {
                    if (n.nodeId == master && n.remoteTimestamp) {
                        masterTimestamp = n.remoteTimestamp;
                    }
                });
            
            _.each(nodes, function (n) {
                var node = _.clone(n);
                node.timestampDisplayPrefix = "";
                node.timestampDisplaySuffix = "";
                if (node['remoteTimestamp']) {
                    node.timestamp = node.remoteTimestamp;
                } else {
                    node.timestamp = node.localTimestamp;
                    node.timestampDisplaySuffix = " (local)";
                }
                if (node.timestamp >= moment().utc() + 10*1000) {
                    // if server reports time significantly in future, report this, with no timestampe
                    node.timestampDisplayPrefix = "server clock in future by "+
                        moment.duration(moment(node.timestamp).diff(moment())).humanize();
                    node.timestamp = "";
                    node.timestampDisplay = "";
                } else {
                    // else use timestamp
                    if (node.timestamp >= moment().utc()) {
                        // but if just a little bit in future, backdate to show "a few seconds ago"
                        node.timestamp = moment().utc()-1;
                    }
                    node.timestampDisplay = moment(node.timestamp).fromNow();
                }
                
                node.isSelf = node.nodeId == self;
                node.isMaster = self == master;
                if (node.status == "TERMINATED") {
                    node.isTerminated = true;
                    node.isPretendMaster = false;
                    node.isStale = false;
                } else {
                    node.isTerminated = false;
                    node.isPretendMaster = (!node.isMaster && node.status == "MASTER" && master != node.nodeId);
                    node.isStale = (masterTimestamp && node.timestamp + 30*1000 < masterTimestamp);
                }
                 
                $target.append(nodeRowTemplate(node));
            });
        },
        updateTimestamps: function() {
            this.$(".timestamp").each(function(index, t) {
                t = $(t);
                var timestamp = t.data("timestamp");
                t.html(_.escape(moment(timestamp).fromNow()));
            });
        }
    });

    return HASummaryView;
});