/*
 *  Copyright (c) 2012 The WebM 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 <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>

#include "adaptation_set.h"
#include "dash_model.h"
#include "period.h"
#include "representation.h"

using std::string;
using webm_dash::DashModel;
using webm_dash::AdaptationSet;
using webm_dash::Period;
using webm_dash::Representation;

static const char VERSION_STRING[] = "1.0.3.0";

static void Usage() {
  printf("Usage: webm_dash_manifest [-o output_file] [-p options] ");
  printf("<-as [as options] <-r [r options]>... >...\n");
  printf("\n");
  printf("Main options:\n");
  printf("-h | -?               show help\n");
  printf("-v                    show version\n");
  printf("-url <string> [...]   Base URL list\n");
  printf("-profile <string>     Set profile.\n");
  printf("\n");
  printf("Period (-p) options:\n");
  printf("-duration <double>    duration in seconds\n");
  printf("-id <string>          id of the Period\n");
  printf("-start <double>       start time in seconds\n");
  printf("\n");
  printf("AdaptationSet (-as) options:\n");
  printf("-id <string>          id of the AdaptationSet\n");
  printf("-lang <string>        lang of the AdaptationSet\n");
  printf("\n");
  printf("Representation (-r) options:\n");
  printf("-id <string>          id of the Media\n");
  printf("-file <string>        Input file\n");
  printf("\n");
}

static bool ParseOption(const string& option, string* name, string* value) {
  if (!name || !value)
    return false;

  const size_t equal_sign = option.find_first_of('=');
  if (equal_sign == string::npos)
    return false;

  *name = option.substr(0, equal_sign);
  *value = option.substr(equal_sign + 1, string::npos);
  return true;
}

static void ParseAdaptationSetOptions(const string& option_list,
                                      AdaptationSet* as) {
  size_t start = 0;
  size_t end = option_list.find_first_of(',');
  for (;;) {
    const string option = option_list.substr(start, end - start);
    string name;
    string value;
    if (ParseOption(option, &name, &value)) {
      if (name == "id") {
        as->set_id(value);
      } else if (name == "lang") {
        as->set_lang(value);
      }
    }

    if (end == string::npos)
      break;
    start = end + 1;
    end = option_list.find_first_of(',', start);
  }
}

static double StringToDouble(const std::string& s) {
  return strtod(s.c_str(), NULL);
}

static void ParsePeriodOptions(const string& option_list, Period* period) {
  size_t start = 0;
  size_t end = option_list.find_first_of(',');
  for (;;) {
    const string option = option_list.substr(start, end - start);
    string name;
    string value;
    if (ParseOption(option, &name, &value)) {
      if (name == "id") {
        period->set_id(value);
      } else if (name == "duration") {
        period->set_duration(StringToDouble(value));
      } else if (name == "start") {
        period->set_start(StringToDouble(value));
      }
    }

    if (end == string::npos)
      break;
    start = end + 1;
    end = option_list.find_first_of(',', start);
  }
}

static void ParseRepresentationOptions(const string& option_list,
                                       DashModel* model,
                                       Representation* r) {
  size_t start = 0;
  size_t end = option_list.find_first_of(',');
  for (;;) {
    const string option = option_list.substr(start, end - start);
    string name;
    string value;
    if (ParseOption(option, &name, &value)) {
      if (name == "id") {
        r->set_id(value);
      } else if (name == "file") {
        model->AppendInputFile(value);
        r->set_webm_filename(value);
      }
    }

    if (end == string::npos)
      break;
    start = end + 1;
    end = option_list.find_first_of(',', start);
  }
}

static bool ParseMainCommandLine(int argc,
                                 char* argv[],
                                 DashModel* model) {
  if (argc < 2) {
    Usage();
    return false;
  }

  if (!model) {
    fprintf(stderr, "model parameter is NULL.\n");
    return EXIT_FAILURE;
  }

  const int argc_check = argc - 1;
  for (int i = 1; i < argc; ++i) {
    if (!strcmp("-p", argv[i]) && i < argc_check) {
      model->AddPeriod();
      Period* const p = model->CurrentPeriod();
      const string option_list(argv[++i]);
      ParsePeriodOptions(option_list, p);
    } else if (!strcmp("-as", argv[i]) && i < argc_check) {
      model->AddAdaptationSet();
      AdaptationSet* const as = model->CurrentAdaptationSet();
      const string option_list(argv[++i]);
      ParseAdaptationSetOptions(option_list, as);
    } else if (!strcmp("-r", argv[i]) && i < argc_check) {
      AdaptationSet* const as = model->CurrentAdaptationSet();
      if (as) {
        as->AddRepresentation();
        Representation* const rep = as->CurrentRepresentation();
        const string option_list(argv[++i]);
        ParseRepresentationOptions(option_list, model, rep);
      }
    } else if (!strcmp("-o", argv[i]) && i < argc_check) {
      model->set_output_filename(argv[++i]);
    } else if (!strcmp("-v", argv[i])) {
      printf("version: %s\n", VERSION_STRING);
    } else if ( (!strcmp("-h", argv[i])) || (!strcmp("-?", argv[i])) ) {
      Usage();
      return false;
    } else if (!strcmp("-url", argv[i]) && i < argc_check) {
      model->AppendBaseUrl(argv[++i]);
    } else if (!strcmp("-profile", argv[i]) && i < argc_check) {
      model->set_profile(argv[++i]);
    }
  }

  return true;
}

int main(int argc, char* argv[]) {
  DashModel model;

  if (!ParseMainCommandLine(argc, argv, &model)) {
    return EXIT_FAILURE;
  }

  if (!model.Init()) {
    fprintf(stderr, "Manifest Model Init() Failed.\n");
    return EXIT_FAILURE;
  }

  if (!model.OutputDashManifestFile()) {
    fprintf(stderr, "OutputDashManifestFile() Failed.\n");
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}
