// Copyright 2017 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/accessibility/screen_reader.h"

#include <string>

#include "base/stringprintf.h"
#include "cobalt/accessibility/internal/live_region.h"
#include "cobalt/accessibility/text_alternative.h"
#include "cobalt/dom/element.h"
#include "cobalt/dom/html_body_element.h"
#include "cobalt/dom/node_list.h"

namespace cobalt {
namespace accessibility {
namespace {
// When text is removed from a live region, add the word "Removed" to indicate
// that the text has been removed.
// TODO: Support other languages.
const char kRemovedFormatString[] = "Removed. %s";
}

ScreenReader::ScreenReader(dom::Document* document, TTSEngine* tts_engine,
                           dom::MutationObserverTaskManager* task_manager)
    : enabled_(true), document_(document), tts_engine_(tts_engine),
      focus_changed_(false) {
  DCHECK(document_ && tts_engine_);
  document_->AddObserver(this);
  live_region_observer_ = new dom::MutationObserver(
      base::Bind(&ScreenReader::MutationObserverCallback, AsWeakPtr()),
      task_manager);
}

ScreenReader::~ScreenReader() {
  live_region_observer_->Disconnect();
  document_->RemoveObserver(this);
}

void ScreenReader::set_enabled(bool value) {
  enabled_ = value;
}

void ScreenReader::OnLoad() {
  dom::MutationObserverInit init;
  init.set_subtree(true);
  // Track character data and node addition/removal for live regions.
  init.set_character_data(true);
  init.set_child_list(true);

  if (document_->body()) {
    live_region_observer_->Observe(document_->body(), init);
  }
}

void ScreenReader::OnFocusChanged() {
  if (focus_changed_) {
    return;
  }
  focus_changed_ = true;
  MessageLoop::current()->PostTask(
      FROM_HERE, base::Bind(&ScreenReader::FocusChangedCallback, AsWeakPtr()));
}

void ScreenReader::FocusChangedCallback() {
  focus_changed_ = false;
  if (!enabled_) {
    return;
  }
  scoped_refptr<dom::Element> element = document_->active_element();
  if (element) {
    std::string text_alternative = ComputeTextAlternative(element);
    tts_engine_->SpeakNow(text_alternative);
  }
}

// MutationObserver callback for tracking the creation and destruction of
// live regions.
void ScreenReader::MutationObserverCallback(
    const MutationRecordSequence& sequence,
    const scoped_refptr<dom::MutationObserver>& observer) {
  // TODO: Only check live regions if text-to-speech is enabled.
  if (!enabled_) {
    return;
  }
  DCHECK_EQ(observer, live_region_observer_);
  for (size_t i = 0; i < sequence.size(); ++i) {
    scoped_refptr<dom::MutationRecord> record = sequence.at(i);

    // Check if the target node is part of a live region.
    scoped_ptr<internal::LiveRegion> live_region =
        internal::LiveRegion::GetLiveRegionForNode(record->target());
    if (!live_region) {
      continue;
    }

    const char* format_string = NULL;
    // Get a list of changed nodes, based on the type of change this was and
    // whether or not the live region cares about this type of change.
    scoped_refptr<dom::NodeList> changed_nodes;
    if (record->type() == base::Tokens::characterData() &&
        live_region->IsMutationRelevant(
            internal::LiveRegion::kMutationTypeText)) {
      changed_nodes = new dom::NodeList();
      changed_nodes->AppendNode(record->target());
    } else if (record->type() == base::Tokens::childList()) {
      if (record->added_nodes() &&
          live_region->IsMutationRelevant(
              internal::LiveRegion::kMutationTypeAddition)) {
        changed_nodes = record->added_nodes();
      }
      if (record->removed_nodes() &&
          live_region->IsMutationRelevant(
              internal::LiveRegion::kMutationTypeRemoval)) {
        changed_nodes = record->removed_nodes();
        format_string = kRemovedFormatString;
      }
    }
    // If we don't have changed nodes, that means that the change was not
    // relevant to this live region.
    if (!changed_nodes || (changed_nodes->length() <= 0)) {
      continue;
    }

    // Check if any of the changed nodes should update the live region
    // atomically.
    bool is_atomic = false;
    for (size_t i = 0; i < changed_nodes->length(); ++i) {
      if (live_region->IsAtomic(changed_nodes->Item(i))) {
        is_atomic = true;
        break;
      }
    }

    std::string text_alternative;
    if (is_atomic) {
      // If the live region updates atomically, then ignore changed_nodes
      // and just get the text alternative from the entire region.
      text_alternative = ComputeTextAlternative(live_region->root());
    } else {
      // Otherwise append all the text alternatives for each node.
      for (size_t i = 0; i < changed_nodes->length(); ++i) {
        text_alternative += ComputeTextAlternative(changed_nodes->Item(i));
      }
    }

    // If we still don't have a text_alternative to speak, continue to the next
    // mutation.
    if (text_alternative.empty()) {
      continue;
    }

    // Provide additional context through a format string, if necessary.
    if (format_string) {
      text_alternative = StringPrintf(format_string, text_alternative.c_str());
    }

    // Utter the text according to whether this live region is assertive or not.
    if (live_region->IsAssertive()) {
      tts_engine_->SpeakNow(text_alternative);
    } else {
      tts_engine_->Speak(text_alternative);
    }
  }
}

}  // namespace accessibility
}  // namespace cobalt
