// Copyright 2017 Google Inc. 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) {
  document_->AddObserver(this);
  live_region_observer_ = new dom::MutationObserver(
      base::Bind(&ScreenReader::MutationObserverCallback,
                 base::Unretained(this)),
      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, base::Unretained(this)));
}

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
