/*
 * Copyright 2011 Google Inc.
 *
 * Licensed 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.
 */

// Author: jmarantz@google.com (Joshua Marantz)

#include "pagespeed/kernel/base/waveform.h"

#include "base/logging.h"
#include "pagespeed/kernel/base/abstract_mutex.h"
#include "pagespeed/kernel/base/basictypes.h"        // for int64
#include "pagespeed/kernel/base/md5_hasher.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/statistics.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/thread_system.h"
#include "pagespeed/kernel/base/timer.h"
#include "pagespeed/kernel/base/writer.h"

namespace net_instaweb {

class MessageHandler;

Waveform::Waveform(ThreadSystem* thread_system, Timer* timer, int capacity,
                   UpDownCounter* metric)
    : timer_(timer),
      capacity_(capacity),
      samples_(new TimeValue[capacity]),
      previous_value_(0.0),
      mutex_(thread_system->NewMutex()),
      metric_(metric) {
  // Note that we don't clear previous_value_ in Clear() because that would
  // get the Waveform out of sync with whatever system is sending it Delta
  // updates.
  Clear();
}

void Waveform::Clear() {
  ScopedMutex lock(mutex_.get());
  start_index_ = 0;
  size_ = 0;
  first_sample_timestamp_us_ = 0;
  total_since_clear_ = 0.0;
  min_ = 0.0;
  max_ = 0.0;
}

int Waveform::Size() {
  // TODO(jmarantz): use reader-lock.
  ScopedMutex lock(mutex_.get());
  return size_;
}

double Waveform::Average() {
  // TODO(jmarantz): use reader-lock.
  ScopedMutex lock(mutex_.get());
  if (size_ == 0) {
    return 0.0;
  }

  // We could make the average by looking at the delta from
  // timer_->NowUs(), rather than prev->first.  But with an active
  // server this won't make much difference, and with a server being
  // debugged I think it's better like this:  the time between the
  // first event and the last event.
  TimeValue* prev = GetSample(size_ - 1);
  int64 elapsed_us = prev->first - first_sample_timestamp_us_;
  return (total_since_clear_ / elapsed_us);
}

double Waveform::Minimum() {
  // TODO(jmarantz): use reader-lock.
  ScopedMutex lock(mutex_.get());
  return min_;
}

double Waveform::Maximum() {
  // TODO(jmarantz): use reader-lock.
  ScopedMutex lock(mutex_.get());
  return max_;
}

Waveform::TimeValue* Waveform::GetSample(int index) {
  // Must be called with mutex held.
  DCHECK_LE(0, index);
  DCHECK_GT(size_, index);
  return &samples_[(start_index_ + index) % capacity_];
}

void Waveform::AddDelta(double delta) {
  // TODO(jmarantz): use writer-lock.
  ScopedMutex lock(mutex_.get());
  AddHelper(previous_value_ + delta);
  if (metric_ != NULL) {
    metric_->Add(static_cast<int64>(delta));
  }
}

void Waveform::Add(double value) {
  // TODO(jmarantz): use writer-lock.
  ScopedMutex lock(mutex_.get());
  AddHelper(value);
  if (metric_ != NULL) {
    metric_->Set(static_cast<int64>(value));
  }
}

void Waveform::AddHelper(double value) {
  previous_value_ = value;
  int64 now_us = timer_->NowUs();
  if (size_ == 0) {
    max_ = value;
    min_ = value;
    first_sample_timestamp_us_ = now_us;
  } else {
    TimeValue* prev = GetSample(size_ - 1);
    int64 elapsed_us = now_us - prev->first;
    total_since_clear_ += elapsed_us * prev->second;  // time-weighted values
    if (value < min_) {
      min_ = value;
    } else if (value > max_) {
      max_ = value;
    }
  }

  if (size_ == capacity_) {
    start_index_ = (start_index_ + 1) % capacity_;
  } else {
    ++size_;
  }
  TimeValue* tv = GetSample(size_ - 1);
  tv->first = now_us;
  tv->second = value;
}

// See http://code.google.com/apis/chart/interactive/docs/gallery/linechart.html
namespace {

const char kChartApiLoad[] =
    "<script type='text/javascript' src='https://www.google.com/jsapi'>"
    "</script>\n"
    "<script type='text/javascript'>\n"
    "  google.load('visualization', '1', {packages:['corechart']});\n"
    "  google.setOnLoadCallback(drawWaveforms);\n"
    "  var google_waveforms = new Array();\n"
    "  function drawWaveform(title, id, legend, points) {\n"
    "    var data = new google.visualization.DataTable();\n"
    "    data.addColumn('number', 'Time (ms)');\n"
    "    data.addColumn('number', legend);\n"
    "    data.addRows(points.length);\n"
    "    var min_x = 0;\n"
    "    var max_x = 0;\n"
    "    var min_y = 0;\n"
    "    var max_y = 0;\n"
    "    for (var i = 0; i < points.length; ++i) {\n"
    "      var point = points[i];\n"
    "      var x = point[0];\n"
    "      var y = point[1];\n"
    "      if ((i == 0) || (x < min_x)) { min_x = x; }\n"
    "      if ((i == 0) || (x > max_x)) { max_x = x; }\n"
    "      if ((i == 0) || (y < min_y)) { min_y = y; }\n"
    "      if ((i == 0) || (y > max_y)) { max_y = y; }\n"
    "      data.setValue(i, 0, x);\n"
    "      data.setValue(i, 1, y);\n"
    "    }\n"
    "    var chart = new google.visualization.ScatterChart(\n"
    "        document.getElementById(id));\n"
    "    chart.draw(data, {\n"
    "        lineWidth: 1,\n"
    "        pointSize: 3,\n"
    "        width: 800, height: 480, title: title, legend: 'none',\n"
    "        hAxis: {title: 'time (ms)', minValue: min_x, "
    "maxValue: 1.1 * max_x},\n"
    "        vAxis: {minValue: min_y, maxValue: 1.1 * "
    "max_y}});\n"
    "  }\n"
    "  function drawWaveforms() {\n"
    "    for (var i = 0; i < google_waveforms.length; ++i) {\n"
    "      var w = google_waveforms[i];\n"
    "      w();\n"
    "    }\n"
    "  }\n"
    "  function addWaveform(title, id, legend, points) {\n"
    "    google_waveforms.push(function() {drawWaveform(title, id, legend, "
    "points);});\n"
    "  }\n"
    "</script>";

const char kChartWaveformPrefixFormat[] =
    "<script type='text/javascript'>\n"
    "  addWaveform('%s', '%s', '%s', [\n";  // title, id, legend

const char kSampleFormat[] =
    "    [%f, %f],\n";

const char kWaveformSuffixFormat[] =
    "]);\n"
    "</script>\n"
    "<div id='%s'></div>\n";

}  // namespace

void Waveform::RenderHeader(Writer* writer, MessageHandler* handler) {
  writer->Write(kChartApiLoad, handler);
}

void Waveform::Render(const StringPiece& title, const StringPiece& label,
                      Writer* writer, MessageHandler* handler) {
  ScopedMutex lock(mutex_.get());
  if (size_ == 0) {
    writer->Write(StrCat(title, ": no data"), handler);
  } else {
    TimeValue* tv = GetSample(0);
    int64 start_time_us = tv->first;

    MD5Hasher hasher;
    GoogleString div_id = hasher.Hash(title);

    writer->Write(StringPrintf(kChartWaveformPrefixFormat,
                               title.as_string().c_str(),
                               div_id.c_str(),
                               label.as_string().c_str()),
                  handler);

    for (int i = 0; i < size_; ++i) {
      tv = GetSample(i);
      int64 delta_us = tv->first - start_time_us;
      writer->Write(StringPrintf(kSampleFormat, delta_us / 1000.0,
                                 static_cast<double>(tv->second)),
                    handler);
    }

    writer->Write(StringPrintf(kWaveformSuffixFormat, div_id.c_str()),
                  handler);
  }
}

}  // namespace net_instaweb
