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

#include "kudu/tablet/svg_dump.h"

#include <algorithm>
#include <ctime>
#include <string>
#include <unordered_set>
#include <vector>

#include <gflags/gflags.h>
#include <glog/logging.h>

#include "kudu/gutil/macros.h"
#include "kudu/gutil/map-util.h"
#include "kudu/gutil/stringprintf.h"
#include "kudu/gutil/strings/substitute.h"
#include "kudu/gutil/strings/util.h"
#include "kudu/tablet/rowset_info.h"
#include "kudu/util/env.h"
#include "kudu/util/flag_tags.h"
#include "kudu/util/slice.h"
#include "kudu/util/status.h"

// Flag to dump SVGs of every compaction decision.
//
// After dumping, these may be converted to an animation using a series of
// commands like:
// $ for x in compaction-*svg ; do convert $x $x.png ; done
// $ mencoder mf://compaction*png -mf fps=1 -ovc lavc -o compactions.avi
DEFINE_string(compaction_policy_dump_svgs_pattern, "",
              "File path into which to dump SVG visualization of "
              "selected compactions. This is mostly useful in "
              "the context of unit tests and benchmarks. "
              "The special string 'TIME' will be substituted "
              "with the compaction selection timestamp.");
TAG_FLAG(compaction_policy_dump_svgs_pattern, hidden);

using std::endl;
using std::ostream;
using std::string;
using std::unordered_set;
using std::vector;
using strings::Substitute;

namespace kudu {
namespace tablet {

namespace {

// Organize the input rowsets into rows for presentation.  This simply
// distributes 'rowsets' into separate vectors in 'rows' such that
// within any given row, none of the rowsets overlap in keyspace.
void OrganizeSVGRows(const vector<RowSetInfo>& candidates,
                     vector<vector<const RowSetInfo*>>* rows) {
  DCHECK(rows);
  rows->clear();
  for (const auto& candidate : candidates) {
    // Slot into the first row which fits it.
    bool found_slot = false;
    for (auto& row : *rows) {
      // If this candidate doesn't intersect any other rowsets already in this
      // row, we can put it in this row.
      auto fits_in_row = std::none_of(row.begin(),
                                      row.end(),
                                      [&candidate](const RowSetInfo* already_in_row) {
                                        return candidate.Intersects(*already_in_row);
                                      });
      if (fits_in_row) {
        row.push_back(&candidate);
        found_slot = true;
        break;
      }
    }
    // If we couldn't find a spot in any existing row, add a new row
    // to the bottom of the SVG.
    if (!found_slot) {
      rows->push_back({ &candidate });
    }
  }
}

void DumpSVG(const vector<RowSetInfo>& candidates,
             const unordered_set<const RowSet*>& picked,
             ostream* outptr) {
  CHECK(outptr);
  CHECK(outptr->good());
  ostream& out = *outptr;

  vector<vector<const RowSetInfo*>> svg_rows;
  OrganizeSVGRows(candidates, &svg_rows);

  const char *kPickedColor = "#f66"; // Light red.
  const char *kDefaultColor = "#666"; // Dark gray.
  constexpr double kTotalWidth = 1200.0;
  constexpr int kRowHeight = 15;
  constexpr double kHeaderHeight = 60.0;
  const double kTotalHeight = kRowHeight * svg_rows.size() + kHeaderHeight;

  out << Substitute(
      R"(<svg version="1.1" width="$0" height="$1" viewBox="0 0 $0 $1" )"
      R"(xmlns="http://www.w3.org/2000/svg">)",
      kTotalWidth, kTotalHeight)
      << endl;

  // Background.
  out << Substitute(R"(<rect x="0" y="0" width="$0" height="$1" fill="#fff"/>)",
                    kTotalWidth, kTotalHeight)
      << endl;

  for (auto row_index = 0; row_index < svg_rows.size(); row_index++) {
    const vector<const RowSetInfo *> &row = svg_rows[row_index];

    const auto y = kRowHeight * row_index + kHeaderHeight;
    for (const RowSetInfo *cand : row) {
      const char *color = ContainsKey(picked, cand->rowset()) ? kPickedColor :
                                                                kDefaultColor;
      const auto x = cand->cdf_min_key() * kTotalWidth;
      const auto width = cand->width() * kTotalWidth;
      out << Substitute(
          R"(<rect x="$0" y="$1" width="$2" height="$3" stroke="#000" fill="$4"/>)",
          x, y, width, kRowHeight, color)
          << endl;
    }
  }

  out << "</svg>" << endl;
}

void PrintXMLHeader(ostream* out) {
  CHECK(out);
  CHECK(out->good());
  *out << R"(<?xml version="1.0" standalone="no"?>)"
       << endl
       << R"(<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" )"
       << R"("http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">)"
       << endl;
}

} // anonymous namespace

void DumpCompactionSVG(const vector<RowSetInfo>& candidates,
                       const unordered_set<const RowSet*>& picked,
                       ostream* out,
                       bool print_xml_header) {
  CHECK(out);
  VLOG(1) << "Dumping SVG of DiskRowSetLayout with"
          << (print_xml_header ? "" : "out") << " XML header";
  if (print_xml_header) {
    PrintXMLHeader(out);
  }
  DumpSVG(candidates, picked, out);
}

void DumpCompactionSVGToFile(const vector<RowSetInfo>& candidates,
                             const unordered_set<const RowSet*>& picked) {
  const string& pattern = FLAGS_compaction_policy_dump_svgs_pattern;
  if (pattern.empty()) {
    return;
  }
  const string path = StringReplace(pattern,
                                    "TIME",
                                    StringPrintf("%ld", time(nullptr)),
                                    /*replace_all=*/true);
  std::ostringstream buf;
  DumpCompactionSVG(candidates, picked, &buf, /*print_xml_header=*/true);
  WARN_NOT_OK(WriteStringToFile(Env::Default(), buf.str(), path),
              "unable to dump rowset compaction SVG to file");
}

} // namespace tablet
} // namespace kudu
