/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "modules/remote_bitrate_estimator/test/bwe_test_baselinefile.h"

#include <stdio.h>

#include <algorithm>
#include <memory>
#include <vector>

#include "modules/remote_bitrate_estimator/test/bwe_test_fileutils.h"
#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h"
#include "rtc_base/constructormagic.h"
#include "test/testsupport/fileutils.h"

namespace webrtc {
namespace testing {
namespace bwe {

// The format of BWE test baseline files is extremely simple:
//   1. All read/written entities are 32-bit unsigned integers in network byte
//      order (Big Endian).
//   2. Files beging with a 2 word header containing a magic marker and file
//      format version indicator. The Magic marker reads "BWE!" in a hex dump.
//   3. Each estimate is logged as a pair of words: time in milliseconds and
//      estimated bit rate, in bits per second.
const uint32_t kMagicMarker = 0x42574521;
const uint32_t kFileVersion1 = 0x00000001;
const char kResourceSubDir[] = "remote_bitrate_estimator";

class BaseLineFileVerify : public BaseLineFileInterface {
 public:
  // If |allow_missing_file| is set, VerifyOrWrite() will return true even if
  // the baseline file is missing. This is the default when verifying files, but
  // not when updating (i.e. we always write it out if missing).
  BaseLineFileVerify(const std::string& filepath, bool allow_missing_file)
      : reader_(),
        fail_to_read_response_(false) {
    std::unique_ptr<ResourceFileReader> reader;
    reader.reset(ResourceFileReader::Create(filepath, "bin"));
    if (!reader.get()) {
      printf("WARNING: Missing baseline file for BWE test: %s.bin\n",
             filepath.c_str());
      fail_to_read_response_ = allow_missing_file;
    } else {
      uint32_t magic_marker = 0;
      uint32_t file_version = 0;
      if (reader->Read(&magic_marker) && magic_marker == kMagicMarker &&
          reader->Read(&file_version) && file_version == kFileVersion1) {
        reader_.swap(reader);
      } else {
        printf("WARNING: Bad baseline file header for BWE test: %s.bin\n",
               filepath.c_str());
      }
    }
  }
  virtual ~BaseLineFileVerify() {}

  virtual void Estimate(int64_t time_ms, uint32_t estimate_bps) {
    if (reader_.get()) {
      uint32_t read_ms = 0;
      uint32_t read_bps = 0;
      if (reader_->Read(&read_ms) && read_ms == time_ms &&
          reader_->Read(&read_bps) && read_bps == estimate_bps) {
      } else {
        printf("ERROR: Baseline differs starting at: %d ms (%d vs %d)!\n",
            static_cast<uint32_t>(time_ms), estimate_bps, read_bps);
        reader_.reset(NULL);
      }
    }
  }

  virtual bool VerifyOrWrite() {
    if (reader_.get()) {
      if (reader_->IsAtEnd()) {
        return true;
      } else {
        printf("ERROR: Baseline file contains more data!\n");
        return false;
      }
    }
    return fail_to_read_response_;
  }

 private:
  std::unique_ptr<ResourceFileReader> reader_;
  bool fail_to_read_response_;

  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(BaseLineFileVerify);
};

class BaseLineFileUpdate : public BaseLineFileInterface {
 public:
  BaseLineFileUpdate(const std::string& filepath,
                     BaseLineFileInterface* verifier)
      : verifier_(verifier),
        output_content_(),
        filepath_(filepath) {
    output_content_.push_back(kMagicMarker);
    output_content_.push_back(kFileVersion1);
  }
  virtual ~BaseLineFileUpdate() {}

  virtual void Estimate(int64_t time_ms, uint32_t estimate_bps) {
    verifier_->Estimate(time_ms, estimate_bps);
    output_content_.push_back(static_cast<uint32_t>(time_ms));
    output_content_.push_back(estimate_bps);
  }

  virtual bool VerifyOrWrite() {
    if (!verifier_->VerifyOrWrite()) {
      std::string dir_path = webrtc::test::OutputPath() + kResourceSubDir;
      if (!webrtc::test::CreateDir(dir_path)) {
        printf("WARNING: Cannot create output dir: %s\n", dir_path.c_str());
        return false;
      }
      std::unique_ptr<OutputFileWriter> writer;
      writer.reset(OutputFileWriter::Create(filepath_, "bin"));
      if (!writer.get()) {
        printf("WARNING: Cannot create output file: %s.bin\n",
            filepath_.c_str());
        return false;
      }
      printf("NOTE: Writing baseline file for BWE test: %s.bin\n",
             filepath_.c_str());
      for (std::vector<uint32_t>::iterator it = output_content_.begin();
          it != output_content_.end(); ++it) {
        writer->Write(*it);
      }
      return true;
    }
    printf("NOTE: No change, not writing: %s\n", filepath_.c_str());
    return true;
  }

 private:
  std::unique_ptr<BaseLineFileInterface> verifier_;
  std::vector<uint32_t> output_content_;
  std::string filepath_;

  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(BaseLineFileUpdate);
};

BaseLineFileInterface* BaseLineFileInterface::Create(
    const std::string& filename, bool write_output_file) {
  std::string filepath = filename;
  std::replace(filepath.begin(), filepath.end(), '/', '_');
  filepath = std::string(kResourceSubDir) + "/" + filepath;

  std::unique_ptr<BaseLineFileInterface> result;
  result.reset(new BaseLineFileVerify(filepath, !write_output_file));
  if (write_output_file) {
    // Takes ownership of the |verifier| instance.
    result.reset(new BaseLineFileUpdate(filepath, result.release()));
  }
  return result.release();
}
}  // namespace bwe
}  // namespace testing
}  // namespace webrtc
