#include "broadcast_table.h"
#include <saas/deploy_manager/server/client/client.h>
#include <library/cpp/json/json_reader.h>

namespace NRTYDeploy {

    bool TScriptBroadcastTable::PrepareCustom(IDeployInfoRequest& request) {
        ByReplica = request.GetRD().CgiParam.Get("by_replicas") == "true";
        return true;
    }

    void TScriptBroadcastTable::DoPrepareJsonForReply(const TBroadcastSlotData& slot, NJson::TJsonValue& reply) {
        TString slotData = "";
        bool keyFindProblem = false;
        if (ByReplica) {
            TReplicaInfo info(slot.ServiceName, slot.ConfigType);
            TGuard<TMutex> g(PrepareJsonMutex);
            TDataByFilter& dataByFilter = ReplicaData[info];
            for (NUtil::TJsonFilter::TFilters::const_iterator f = Filter.GetFilters().begin(); f != Filter.GetFilters().end(); ++f) {
                const NJson::TJsonValue* value = reply.GetValueByPath(*f, '.');
                if (value) {
                    dataByFilter.DBF[*f].AddData(value->GetStringRobust());
                }
                else {
                    dataByFilter.DBF[*f].CountFails++;
                    dataByFilter.HasFails = true;
                }
            }
        } else {
            for (NUtil::TJsonFilter::TFilters::const_iterator f = Filter.GetFilters().begin(); f != Filter.GetFilters().end(); ++f) {
                const NJson::TJsonValue* value = reply.GetValueByPath(*f, '.');
                if (value) {
                    slotData += "<td align=\"center\">";
                    slotData += value->GetStringRobust();
                    slotData += "</td>";
                } else {
                    slotData += "<td align=\"center\"><font color=\"#FF0000\">";
                    slotData += reply.GetStringRobust().substr(0, 100);
                    slotData += "</font></td>";
                    keyFindProblem = true;
                }
            }
            if (!keyFindProblem)
                slotData = "<td align=\"center\">" + slot.SMHost.GetSlotName() + "</td>" + slotData;
            else
                slotData = "<td bgcolor=\"red\" align=\"center\">" + slot.SMHost.GetSlotName() + "</td>" + slotData;
        }
        TGuard<TMutex> g(PrepareJsonMutex);
        HtmlData[slot] = slotData;
    }

    bool TScriptBroadcastTable::MakeReport(IOutputStream& ss) {
        ss << "<table cellspcing=\"2\" cellpadding=\"2\" border=\"1\"><tr>";
        ss << "<td align=\"center\">Service</td><td align=\"center\">Config</td>";
        if (!ByReplica)
            ss << "<td align = \"center\">Slot</td>";
        for (NUtil::TJsonFilter::TFilters::const_iterator f = Filter.GetFilters().begin(); f != Filter.GetFilters().end(); ++f)
            ss << "<td align=\"center\">" << *f << "</td>";
        ss << "</tr>";
        TString curServ;
        TString curConfType;
        if (ByReplica) {
            for (TMap<TReplicaInfo, TDataByFilter>::const_iterator i = ReplicaData.begin(); i != ReplicaData.end(); ++i) {
                ss << "<tr>";
                const TReplicaInfo& hr = i->first;
                if (hr.ServiceName != curServ) {
                    int hostNum = 0;
                    for (TMap<TReplicaInfo, TDataByFilter>::const_iterator j = i; j != ReplicaData.end() && j->first.ServiceName == hr.ServiceName; ++j)
                        ++hostNum;
                    ss << "<td valign=\"center\" align=\"center\" rowspan=\"" << hostNum << "\">" << hr.ServiceName << "</td>";
                }
                if (hr.ConfigType != curConfType || hr.ServiceName != curServ) {
                    int replicaNum = 0;
                    for (TMap<TReplicaInfo, TDataByFilter>::const_iterator j = i; j != ReplicaData.end() && j->first.ConfigType == hr.ConfigType && j->first.ServiceName == hr.ServiceName; ++j)
                        ++replicaNum;
                    if (i->second.HasFails)
                        ss << "<td bgcolor=\"#FF0000\" valign=\"center\" align=\"center\" rowspan=\"" << replicaNum << "\">" << hr.ConfigType << "</td>";
                    else
                        ss << "<td valign=\"center\" align=\"center\" rowspan=\"" << replicaNum << "\">" << hr.ConfigType << "</td>";
                }
                curConfType = hr.ConfigType;
                curServ = hr.ServiceName;

                for (NUtil::TJsonFilter::TFilters::const_iterator f = Filter.GetFilters().begin(); f != Filter.GetFilters().end(); ++f) {
                    TMap<TString, TAggrData>::const_iterator dbf = i->second.DBF.find(*f);
                    TAggrData info;
                    TString toReport;
                    if (dbf == i->second.DBF.end()) {
                        info.CountFails = 1;
                        toReport = "Incorrect filter name";
                    }
                    else {
                        info = dbf->second;
                        toReport = info.Aggregate();
                    }
                    if (info.CountFails) {
                        ss << "<td align=\"center\"><font color=\"#FF0000\">";
                    }
                    else {
                        ss << "<td align=\"center\">";
                    }
                    ss << toReport;
                    if (info.CountFails) {
                        ss << " (" << info.CountFails << ")";
                        ss << "</font>";
                    }
                    ss << "</td>";
                }
                ss << "</tr>";
            }
        } else {
            for (TSlotToValues::const_iterator i = HtmlData.begin(); i != HtmlData.end(); ++i) {
                ss << "<tr>";
                const TBroadcastSlotData& hr = i->first;
                if (hr.ServiceName != curServ) {
                    int hostNum = 0;
                    for (TSlotToValues::const_iterator j = i; j != HtmlData.end() && j->first.ServiceName == hr.ServiceName; ++j)
                        ++hostNum;
                    ss << "<td valign=\"center\" align=\"center\" rowspan=\"" << hostNum << "\">" << hr.ServiceName << "</td>";
                }
                if (hr.ConfigType != curConfType || hr.ServiceName != curServ) {
                    int replicaNum = 0;
                    for (TSlotToValues::const_iterator j = i; j != HtmlData.end() && j->first.ConfigType == hr.ConfigType && j->first.ServiceName == hr.ServiceName; ++j)
                        ++replicaNum;
                    ss << "<td valign=\"center\" align=\"center\" rowspan=\"" << replicaNum << "\">" << hr.ConfigType << "</td>";
                }
                curConfType = hr.ConfigType;
                curServ = hr.ServiceName;
                ss << i->second;
                ss << "</tr>";
            }
        }
        ss << "</table>";
        return true;
    }

    TString TScriptBroadcastTable::Help() {
        return "http://localhost:12001/broadcast_table?command=get_info_server&ctype=stable&&filter=result.Svn_author,result.Svn_revision&service=";
    }

    IScript::TFactory::TRegistrator<TScriptBroadcastTable> TScriptBroadcastTable::Registrator("broadcast_table");
}
