/*
 * libjingle
 * Copyright 2004--2011, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "talk/app/webrtc/webrtcjson.h"

#ifdef WEBRTC_RELATIVE_PATH
#include "json/json.h"
#else
#include "third_party/jsoncpp/json.h"
#endif

// TODO: Remove webrtcsession.h once we can get size from signaling.
// webrtcsession.h is for kDefaultVideoCodecWidth and kDefaultVideoCodecHeight.
#include "talk/app/webrtc/webrtcsession.h"
#include "talk/base/json.h"
#include "talk/base/logging.h"
#include "talk/base/stringutils.h"
#include "talk/session/phone/codec.h"
#include "talk/session/phone/mediasessionclient.h"

namespace webrtc {
static const int kIceComponent = 1;
static const int kIceFoundation = 1;

static std::vector<Json::Value> ReadValues(const Json::Value& value,
                                           const std::string& key);

static bool BuildMediaMessage(
    const cricket::ContentInfo& content_info,
    const std::vector<cricket::Candidate>& candidates,
    bool video,
    Json::Value* value);

static bool BuildRtpMapParams(
    const cricket::ContentInfo& audio_offer,
    bool video,
    std::vector<Json::Value>* rtpmap);

static bool BuildAttributes(const std::vector<cricket::Candidate>& candidates,
                            bool video,
                            std::vector<Json::Value>* jcandidates);

static std::string Serialize(const Json::Value& value);
static bool Deserialize(const std::string& message, Json::Value* value);

static bool ParseRtcpMux(const Json::Value& value);
static bool ParseAudioCodec(const Json::Value& value,
                            cricket::AudioContentDescription* content);
static bool ParseVideoCodec(const Json::Value& value,
                            cricket::VideoContentDescription* content);
static bool ParseIceCandidates(const Json::Value& value,
                               std::vector<cricket::Candidate>* candidates);

static Json::Value ReadValue(const Json::Value& value, const std::string& key);
static std::string ReadString(const Json::Value& value, const std::string& key);
static uint32 ReadUInt(const Json::Value& value, const std::string& key);

static void Append(Json::Value* object, const std::string& key, bool value);
static void Append(Json::Value* object, const std::string& key, int value);
static void Append(Json::Value* object, const std::string& key,
                   const std::string& value);
static void Append(Json::Value* object, const std::string& key, uint32 value);
static void Append(Json::Value* object, const std::string& key,
                   const Json::Value& value);
static void Append(Json::Value* object,
                   const std::string& key,
                   const std::vector<Json::Value>& values);

bool GetJsonSignalingMessage(
    const cricket::SessionDescription* sdp,
    const std::vector<cricket::Candidate>& candidates,
    std::string* signaling_message) {
  const cricket::ContentInfo* audio_content = GetFirstAudioContent(sdp);
  const cricket::ContentInfo* video_content = GetFirstVideoContent(sdp);

  std::vector<Json::Value> media;
  if (audio_content) {
    Json::Value value;
    BuildMediaMessage(*audio_content, candidates, false, &value);
    media.push_back(value);
  }

  if (video_content) {
    Json::Value value;
    BuildMediaMessage(*video_content, candidates, true, &value);
    media.push_back(value);
  }

  Json::Value signal;
  Append(&signal, "media", media);

  // Now serialize.
  *signaling_message = Serialize(signal);

  return true;
}

bool BuildMediaMessage(
    const cricket::ContentInfo& content_info,
    const std::vector<cricket::Candidate>& candidates,
    bool video,
    Json::Value* params) {
  if (video) {
    Append(params, "label", 2);  // always video 2
  } else {
    Append(params, "label", 1);  // always audio 1
  }

  const cricket::MediaContentDescription* media_info =
  static_cast<const cricket::MediaContentDescription*> (
      content_info.description);
  if (media_info->rtcp_mux()) {
    Append(params, "rtcp_mux", true);
  }

  std::vector<Json::Value> rtpmap;
  if (!BuildRtpMapParams(content_info, video, &rtpmap)) {
    return false;
  }

  Append(params, "rtpmap", rtpmap);

  Json::Value attributes;
  std::vector<Json::Value> jcandidates;

  if (!BuildAttributes(candidates, video, &jcandidates)) {
    return false;
  }
  Append(&attributes, "candidate", jcandidates);
  Append(params, "attributes", attributes);
  return true;
}

bool BuildRtpMapParams(const cricket::ContentInfo& content_info,
                       bool video,
                       std::vector<Json::Value>* rtpmap) {
  if (!video) {
    const cricket::AudioContentDescription* audio_offer =
        static_cast<const cricket::AudioContentDescription*>(
            content_info.description);

    std::vector<cricket::AudioCodec>::const_iterator iter =
        audio_offer->codecs().begin();
    std::vector<cricket::AudioCodec>::const_iterator iter_end =
        audio_offer->codecs().end();
    for (; iter != iter_end; ++iter) {
      Json::Value codec;
      std::string codec_str(std::string("audio/").append(iter->name));
      // adding clockrate
      Append(&codec, "clockrate", iter->clockrate);
      Append(&codec, "codec", codec_str);
      Json::Value codec_id;
      Append(&codec_id, talk_base::ToString(iter->id), codec);
      rtpmap->push_back(codec_id);
    }
  } else {
    const cricket::VideoContentDescription* video_offer =
        static_cast<const cricket::VideoContentDescription*>(
            content_info.description);

    std::vector<cricket::VideoCodec>::const_iterator iter =
        video_offer->codecs().begin();
    std::vector<cricket::VideoCodec>::const_iterator iter_end =
        video_offer->codecs().end();
    for (; iter != iter_end; ++iter) {
      Json::Value codec;
      std::string codec_str(std::string("video/").append(iter->name));
      Append(&codec, "codec", codec_str);
      Json::Value codec_id;
      Append(&codec_id, talk_base::ToString(iter->id), codec);
      rtpmap->push_back(codec_id);
    }
  }
  return true;
}

bool BuildAttributes(const std::vector<cricket::Candidate>& candidates,
                     bool video,
                     std::vector<Json::Value>* jcandidates) {
  std::vector<cricket::Candidate>::const_iterator iter =
      candidates.begin();
  std::vector<cricket::Candidate>::const_iterator iter_end =
      candidates.end();
  for (; iter != iter_end; ++iter) {
    if ((video && (!iter->name().compare("video_rtcp") ||
                  (!iter->name().compare("video_rtp")))) ||
        (!video && (!iter->name().compare("rtp") ||
                   (!iter->name().compare("rtcp"))))) {
      Json::Value candidate;
      Append(&candidate, "component", kIceComponent);
      Append(&candidate, "foundation", kIceFoundation);
      Append(&candidate, "generation", iter->generation());
      Append(&candidate, "proto", iter->protocol());
      Append(&candidate, "priority", iter->preference_str());
      Append(&candidate, "ip", iter->address().IPAsString());
      Append(&candidate, "port", iter->address().PortAsString());
      Append(&candidate, "type", iter->type());
      Append(&candidate, "name", iter->name());
      Append(&candidate, "network_name", iter->network_name());
      Append(&candidate, "username", iter->username());
      Append(&candidate, "password", iter->password());
      jcandidates->push_back(candidate);
    }
  }
  return true;
}

std::string Serialize(const Json::Value& value) {
  Json::StyledWriter writer;
  return writer.write(value);
}

bool Deserialize(const std::string& message, Json::Value* value) {
  Json::Reader reader;
  return reader.parse(message, *value);
}

bool ParseJsonSignalingMessage(const std::string& signaling_message,
                               cricket::SessionDescription** sdp,
                               std::vector<cricket::Candidate>* candidates) {
  ASSERT(!(*sdp));  // expect this to be NULL
  // first deserialize message
  Json::Value value;
  if (!Deserialize(signaling_message, &value)) {
    return false;
  }

  // get media objects
  std::vector<Json::Value> mlines = ReadValues(value, "media");
  if (mlines.empty()) {
    // no m-lines found
    return false;
  }

  *sdp = new cricket::SessionDescription();

  // get codec information
  for (size_t i = 0; i < mlines.size(); ++i) {
    if (mlines[i]["label"].asInt() == 1) {
      cricket::AudioContentDescription* audio_content =
          new cricket::AudioContentDescription();
      ParseAudioCodec(mlines[i], audio_content);
      audio_content->set_rtcp_mux(ParseRtcpMux(mlines[i]));
      audio_content->SortCodecs();
      (*sdp)->AddContent(cricket::CN_AUDIO,
                         cricket::NS_JINGLE_RTP, audio_content);
      ParseIceCandidates(mlines[i], candidates);
    } else {
      cricket::VideoContentDescription* video_content =
          new cricket::VideoContentDescription();
      ParseVideoCodec(mlines[i], video_content);

      video_content->set_rtcp_mux(ParseRtcpMux(mlines[i]));
      video_content->SortCodecs();
      (*sdp)->AddContent(cricket::CN_VIDEO,
                         cricket::NS_JINGLE_RTP, video_content);
      ParseIceCandidates(mlines[i], candidates);
    }
  }
  return true;
}

bool ParseRtcpMux(const Json::Value& value) {
  Json::Value rtcp_mux(ReadValue(value, "rtcp_mux"));
  if (!rtcp_mux.empty()) {
    if (rtcp_mux.asBool()) {
      return true;
    }
  }
  return false;
}

bool ParseAudioCodec(const Json::Value& value,
                     cricket::AudioContentDescription* content) {
  std::vector<Json::Value> rtpmap(ReadValues(value, "rtpmap"));
  if (rtpmap.empty())
    return false;

  std::vector<Json::Value>::const_iterator iter =
      rtpmap.begin();
  std::vector<Json::Value>::const_iterator iter_end =
      rtpmap.end();
  for (; iter != iter_end; ++iter) {
    cricket::AudioCodec codec;
    std::string pltype(iter->begin().memberName());
    talk_base::FromString(pltype, &codec.id);
    Json::Value codec_info((*iter)[pltype]);
    std::string codec_name(ReadString(codec_info, "codec"));
    std::vector<std::string> tokens;
    talk_base::split(codec_name, '/', &tokens);
    codec.name = tokens[1];
    codec.clockrate = ReadUInt(codec_info, "clockrate");
    content->AddCodec(codec);
  }

  return true;
}

bool ParseVideoCodec(const Json::Value& value,
                     cricket::VideoContentDescription* content) {
  std::vector<Json::Value> rtpmap(ReadValues(value, "rtpmap"));
  if (rtpmap.empty())
    return false;

  std::vector<Json::Value>::const_iterator iter =
      rtpmap.begin();
  std::vector<Json::Value>::const_iterator iter_end =
      rtpmap.end();
  for (; iter != iter_end; ++iter) {
    cricket::VideoCodec codec;
    std::string pltype(iter->begin().memberName());
    talk_base::FromString(pltype, &codec.id);
    Json::Value codec_info((*iter)[pltype]);
    std::vector<std::string> tokens;
    talk_base::split(codec_info["codec"].asString(), '/', &tokens);
    codec.name = tokens[1];
    // TODO: Remove once we can get size from signaling message.
    codec.width = WebRtcSession::kDefaultVideoCodecWidth;
    codec.height = WebRtcSession::kDefaultVideoCodecHeight;
    content->AddCodec(codec);
  }
  return true;
}

bool ParseIceCandidates(const Json::Value& value,
                        std::vector<cricket::Candidate>* candidates) {
  Json::Value attributes(ReadValue(value, "attributes"));
  std::string ice_pwd(ReadString(attributes, "ice-pwd"));
  std::string ice_ufrag(ReadString(attributes, "ice-ufrag"));

  std::vector<Json::Value> jcandidates(ReadValues(attributes, "candidate"));

  std::vector<Json::Value>::const_iterator iter =
      jcandidates.begin();
  std::vector<Json::Value>::const_iterator iter_end =
      jcandidates.end();
  for (; iter != iter_end; ++iter) {
    cricket::Candidate cand;

    unsigned int generation;
    if (!GetUIntFromJsonObject(*iter, "generation", &generation))
      return false;
    cand.set_generation_str(talk_base::ToString(generation));

    std::string proto;
    if (!GetStringFromJsonObject(*iter, "proto", &proto))
      return false;
    cand.set_protocol(proto);

    std::string priority;
    if (!GetStringFromJsonObject(*iter, "priority", &priority))
      return false;
    cand.set_preference_str(priority);

    std::string str;
    talk_base::SocketAddress addr;
    if (!GetStringFromJsonObject(*iter, "ip", &str))
      return false;
    addr.SetIP(str);
    if (!GetStringFromJsonObject(*iter, "port", &str))
      return false;
    int port;
    if (!talk_base::FromString(str, &port))
      return false;
    addr.SetPort(port);
    cand.set_address(addr);

    if (!GetStringFromJsonObject(*iter, "type", &str))
      return false;
    cand.set_type(str);

    if (!GetStringFromJsonObject(*iter, "name", &str))
      return false;
    cand.set_name(str);

    if (!GetStringFromJsonObject(*iter, "network_name", &str))
      return false;
    cand.set_network_name(str);

    if (!GetStringFromJsonObject(*iter, "username", &str))
      return false;
    cand.set_username(str);

    if (!GetStringFromJsonObject(*iter, "password", &str))
      return false;
    cand.set_password(str);

    candidates->push_back(cand);
  }
  return true;
}

std::vector<Json::Value> ReadValues(
    const Json::Value& value, const std::string& key) {
  std::vector<Json::Value> objects;
  for (Json::Value::ArrayIndex i = 0; i < value[key].size(); ++i) {
    objects.push_back(value[key][i]);
  }
  return objects;
}

Json::Value ReadValue(const Json::Value& value, const std::string& key) {
  return value[key];
}

std::string ReadString(const Json::Value& value, const std::string& key) {
  return value[key].asString();
}

uint32 ReadUInt(const Json::Value& value, const std::string& key) {
  return value[key].asUInt();
}

void Append(Json::Value* object, const std::string& key, bool value) {
  (*object)[key] = Json::Value(value);
}

void Append(Json::Value* object, const std::string& key, int value) {
  (*object)[key] = Json::Value(value);
}

void Append(Json::Value* object, const std::string& key,
            const std::string& value) {
  (*object)[key] = Json::Value(value);
}

void Append(Json::Value* object, const std::string& key, uint32 value) {
  (*object)[key] = Json::Value(value);
}

void Append(Json::Value* object, const std::string& key,
            const Json::Value& value) {
  (*object)[key] = value;
}

void Append(Json::Value* object,
            const std::string & key,
            const std::vector<Json::Value>& values) {
  for (std::vector<Json::Value>::const_iterator iter = values.begin();
      iter != values.end(); ++iter) {
    (*object)[key].append(*iter);
  }
}

}  // namespace webrtc
