// 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) {
  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
