/*
 *  Copyright 2012 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 "pc/dtmfsender.h"

#include <ctype.h>

#include <string>

#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/thread.h"

namespace webrtc {

enum {
  MSG_DO_INSERT_DTMF = 0,
};

// RFC4733
//  +-------+--------+------+---------+
//  | Event | Code   | Type | Volume? |
//  +-------+--------+------+---------+
//  | 0--9  | 0--9   | tone | yes     |
//  | *     | 10     | tone | yes     |
//  | #     | 11     | tone | yes     |
//  | A--D  | 12--15 | tone | yes     |
//  +-------+--------+------+---------+
// The "," is a special event defined by the WebRTC spec. It means to delay for
// 2 seconds before processing the next tone. We use -1 as its code.
static const int kDtmfCodeTwoSecondDelay = -1;
static const int kDtmfTwoSecondInMs = 2000;
static const char kDtmfValidTones[] = ",0123456789*#ABCDabcd";
static const char kDtmfTonesTable[] = ",0123456789*#ABCD";
// The duration cannot be more than 6000ms or less than 40ms. The gap between
// tones must be at least 50 ms.
// Source for values: W3C WEBRTC specification.
// https://w3c.github.io/webrtc-pc/#dom-rtcdtmfsender-insertdtmf
static const int kDtmfDefaultDurationMs = 100;
static const int kDtmfMinDurationMs = 40;
static const int kDtmfMaxDurationMs = 6000;
static const int kDtmfDefaultGapMs = 50;
static const int kDtmfMinGapMs = 30;

// Get DTMF code from the DTMF event character.
bool GetDtmfCode(char tone, int* code) {
  // Convert a-d to A-D.
  char event = toupper(tone);
  const char* p = strchr(kDtmfTonesTable, event);
  if (!p) {
    return false;
  }
  *code = p - kDtmfTonesTable - 1;
  return true;
}

rtc::scoped_refptr<DtmfSender> DtmfSender::Create(
    AudioTrackInterface* track,
    rtc::Thread* signaling_thread,
    DtmfProviderInterface* provider) {
  if (!signaling_thread) {
    return nullptr;
  }
  rtc::scoped_refptr<DtmfSender> dtmf_sender(
      new rtc::RefCountedObject<DtmfSender>(track, signaling_thread, provider));
  return dtmf_sender;
}

DtmfSender::DtmfSender(AudioTrackInterface* track,
                       rtc::Thread* signaling_thread,
                       DtmfProviderInterface* provider)
    : track_(track),
      observer_(NULL),
      signaling_thread_(signaling_thread),
      provider_(provider),
      duration_(kDtmfDefaultDurationMs),
      inter_tone_gap_(kDtmfDefaultGapMs) {
  RTC_DCHECK(signaling_thread_ != NULL);
  // TODO(deadbeef): Once we can use shared_ptr and weak_ptr,
  // do that instead of relying on a "destroyed" signal.
  if (provider_) {
    RTC_DCHECK(provider_->GetOnDestroyedSignal() != NULL);
    provider_->GetOnDestroyedSignal()->connect(
        this, &DtmfSender::OnProviderDestroyed);
  }
}

DtmfSender::~DtmfSender() {
  StopSending();
}

void DtmfSender::RegisterObserver(DtmfSenderObserverInterface* observer) {
  observer_ = observer;
}

void DtmfSender::UnregisterObserver() {
  observer_ = NULL;
}

bool DtmfSender::CanInsertDtmf() {
  RTC_DCHECK(signaling_thread_->IsCurrent());
  if (!provider_) {
    return false;
  }
  return provider_->CanInsertDtmf();
}

bool DtmfSender::InsertDtmf(const std::string& tones,
                            int duration,
                            int inter_tone_gap) {
  RTC_DCHECK(signaling_thread_->IsCurrent());

  if (duration > kDtmfMaxDurationMs || duration < kDtmfMinDurationMs ||
      inter_tone_gap < kDtmfMinGapMs) {
    RTC_LOG(LS_ERROR)
        << "InsertDtmf is called with invalid duration or tones gap. "
           "The duration cannot be more than "
        << kDtmfMaxDurationMs << "ms or less than " << kDtmfMinDurationMs
        << "ms. The gap between tones must be at least " << kDtmfMinGapMs
        << "ms.";
    return false;
  }

  if (!CanInsertDtmf()) {
    RTC_LOG(LS_ERROR)
        << "InsertDtmf is called on DtmfSender that can't send DTMF.";
    return false;
  }

  tones_ = tones;
  duration_ = duration;
  inter_tone_gap_ = inter_tone_gap;
  // Clear the previous queue.
  signaling_thread_->Clear(this, MSG_DO_INSERT_DTMF);
  // Kick off a new DTMF task queue.
  signaling_thread_->PostDelayed(RTC_FROM_HERE, 1, this, MSG_DO_INSERT_DTMF);
  return true;
}

const AudioTrackInterface* DtmfSender::track() const {
  return track_;
}

std::string DtmfSender::tones() const {
  return tones_;
}

int DtmfSender::duration() const {
  return duration_;
}

int DtmfSender::inter_tone_gap() const {
  return inter_tone_gap_;
}

void DtmfSender::OnMessage(rtc::Message* msg) {
  switch (msg->message_id) {
    case MSG_DO_INSERT_DTMF: {
      DoInsertDtmf();
      break;
    }
    default: {
      RTC_NOTREACHED();
      break;
    }
  }
}

void DtmfSender::DoInsertDtmf() {
  RTC_DCHECK(signaling_thread_->IsCurrent());

  // Get the first DTMF tone from the tone buffer. Unrecognized characters will
  // be ignored and skipped.
  size_t first_tone_pos = tones_.find_first_of(kDtmfValidTones);
  int code = 0;
  if (first_tone_pos == std::string::npos) {
    tones_.clear();
    // Fire a “OnToneChange” event with an empty string and stop.
    if (observer_) {
      observer_->OnToneChange(std::string());
    }
    return;
  } else {
    char tone = tones_[first_tone_pos];
    if (!GetDtmfCode(tone, &code)) {
      // The find_first_of(kDtmfValidTones) should have guarantee |tone| is
      // a valid DTMF tone.
      RTC_NOTREACHED();
    }
  }

  int tone_gap = inter_tone_gap_;
  if (code == kDtmfCodeTwoSecondDelay) {
    // Special case defined by WebRTC - The character',' indicates a delay of 2
    // seconds before processing the next character in the tones parameter.
    tone_gap = kDtmfTwoSecondInMs;
  } else {
    if (!provider_) {
      RTC_LOG(LS_ERROR) << "The DtmfProvider has been destroyed.";
      return;
    }
    // The provider starts playout of the given tone on the
    // associated RTP media stream, using the appropriate codec.
    if (!provider_->InsertDtmf(code, duration_)) {
      RTC_LOG(LS_ERROR) << "The DtmfProvider can no longer send DTMF.";
      return;
    }
    // Wait for the number of milliseconds specified by |duration_|.
    tone_gap += duration_;
  }

  // Fire a “OnToneChange” event with the tone that's just processed.
  if (observer_) {
    observer_->OnToneChange(tones_.substr(first_tone_pos, 1));
  }

  // Erase the unrecognized characters plus the tone that's just processed.
  tones_.erase(0, first_tone_pos + 1);

  // Continue with the next tone.
  signaling_thread_->PostDelayed(RTC_FROM_HERE, tone_gap, this,
                                 MSG_DO_INSERT_DTMF);
}

void DtmfSender::OnProviderDestroyed() {
  RTC_LOG(LS_INFO) << "The Dtmf provider is deleted. Clear the sending queue.";
  StopSending();
  provider_ = NULL;
}

void DtmfSender::StopSending() {
  signaling_thread_->Clear(this);
}

}  // namespace webrtc
