/*
 *  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/dtmf_sender.h"

#include <ctype.h>
#include <string.h>

#include "api/task_queue/to_queued_task.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/thread.h"

namespace webrtc {

// 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 kDtmfCommaDelay = -1;
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(
    rtc::Thread* signaling_thread,
    DtmfProviderInterface* provider) {
  if (!signaling_thread) {
    return nullptr;
  }
  return rtc::make_ref_counted<DtmfSender>(signaling_thread, provider);
}

DtmfSender::DtmfSender(rtc::Thread* signaling_thread,
                       DtmfProviderInterface* provider)
    : observer_(nullptr),
      signaling_thread_(signaling_thread),
      provider_(provider),
      duration_(kDtmfDefaultDurationMs),
      inter_tone_gap_(kDtmfDefaultGapMs),
      comma_delay_(kDtmfDefaultCommaDelayMs) {
  RTC_DCHECK(signaling_thread_);
  if (provider_) {
    RTC_DCHECK(provider_->GetOnDestroyedSignal());
    provider_->GetOnDestroyedSignal()->connect(
        this, &DtmfSender::OnProviderDestroyed);
  }
}

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

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

void DtmfSender::UnregisterObserver() {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  observer_ = nullptr;
}

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

bool DtmfSender::InsertDtmf(const std::string& tones,
                            int duration,
                            int inter_tone_gap,
                            int comma_delay) {
  RTC_DCHECK_RUN_ON(signaling_thread_);

  if (duration > kDtmfMaxDurationMs || duration < kDtmfMinDurationMs ||
      inter_tone_gap < kDtmfMinGapMs || comma_delay < 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;
  comma_delay_ = comma_delay;

  // Cancel any remaining tasks for previous tones.
  if (safety_flag_) {
    safety_flag_->SetNotAlive();
  }
  safety_flag_ = PendingTaskSafetyFlag::Create();
  // Kick off a new DTMF task.
  QueueInsertDtmf(RTC_FROM_HERE, 1 /*ms*/);
  return true;
}

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

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

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

int DtmfSender::comma_delay() const {
  RTC_DCHECK_RUN_ON(signaling_thread_);
  return comma_delay_;
}

void DtmfSender::QueueInsertDtmf(const rtc::Location& posted_from,
                                 uint32_t delay_ms) {
  signaling_thread_->PostDelayedHighPrecisionTask(
      ToQueuedTask(safety_flag_,
                   [this] {
                     RTC_DCHECK_RUN_ON(signaling_thread_);
                     DoInsertDtmf();
                   }),
      delay_ms);
}

void DtmfSender::DoInsertDtmf() {
  // 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(), tones_);
      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_DCHECK_NOTREACHED();
    }
  }

  int tone_gap = inter_tone_gap_;
  if (code == kDtmfCommaDelay) {
    // Special case defined by WebRTC - By default, the character ',' indicates
    // a delay of 2 seconds before processing the next character in the tones
    // parameter. The comma delay can be set to a non default value via
    // InsertDtmf to comply with legacy WebRTC clients.
    tone_gap = comma_delay_;
  } 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),
                            tones_.substr(first_tone_pos + 1));
    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.
  QueueInsertDtmf(RTC_FROM_HERE, tone_gap);
}

void DtmfSender::OnProviderDestroyed() {
  RTC_DCHECK_RUN_ON(signaling_thread_);

  RTC_LOG(LS_INFO) << "The Dtmf provider is deleted. Clear the sending queue.";
  StopSending();
  provider_ = nullptr;
}

void DtmfSender::StopSending() {
  if (safety_flag_) {
    safety_flag_->SetNotAlive();
  }
}

}  // namespace webrtc
