// Copyright 2015 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/dom_parser/parser.h"

#include "base/logging.h"
#include "cobalt/dom/document.h"
#include "cobalt/dom/xml_document.h"
#include "cobalt/dom_parser/html_decoder.h"
#include "cobalt/dom_parser/xml_decoder.h"

namespace cobalt {
namespace dom_parser {

scoped_refptr<dom::Document> Parser::ParseDocument(
    const std::string& input, dom::HTMLElementContext* html_element_context,
    const base::SourceLocation& input_location) {
  DCHECK(html_element_context);
  scoped_refptr<dom::Document> document =
      new dom::Document(html_element_context);
  HTMLDecoder html_decoder(document, document, NULL, dom_max_element_depth_,
                           input_location, base::Closure(), error_callback_,
                           false, require_csp_);
  html_decoder.DecodeChunk(input.c_str(), input.length());
  html_decoder.Finish();
  return document;
}

scoped_refptr<dom::XMLDocument> Parser::ParseXMLDocument(
    const std::string& input, dom::HTMLElementContext* html_element_context,
    const base::SourceLocation& input_location) {
  DCHECK(html_element_context);
  scoped_refptr<dom::XMLDocument> xml_document =
      new dom::XMLDocument(html_element_context);
  XMLDecoder xml_decoder(
      xml_document, xml_document, NULL, dom_max_element_depth_, input_location,
      base::Closure(),
      base::Bind(&Parser::ErrorCallback, base::Unretained(this)));
  xml_decoder.DecodeChunk(input.c_str(), input.length());
  xml_decoder.Finish();
  return xml_document;
}

void Parser::ParseDocumentFragment(
    const std::string& input, const scoped_refptr<dom::Document>& document,
    const scoped_refptr<dom::Node>& parent_node,
    const scoped_refptr<dom::Node>& reference_node,
    const base::SourceLocation& input_location) {
  HTMLDecoder html_decoder(
      document, parent_node, reference_node, dom_max_element_depth_,
      input_location, base::Closure(), error_callback_, false, require_csp_);
  html_decoder.DecodeChunk(input.c_str(), input.length());
  html_decoder.Finish();
}

void Parser::ParseXMLDocumentFragment(
    const std::string& input,
    const scoped_refptr<dom::XMLDocument>& xml_document,
    const scoped_refptr<dom::Node>& parent_node,
    const scoped_refptr<dom::Node>& reference_node,
    const base::SourceLocation& input_location) {
  XMLDecoder xml_decoder(
      xml_document, parent_node, reference_node, dom_max_element_depth_,
      input_location, base::Closure(),
      base::Bind(&Parser::ErrorCallback, base::Unretained(this)));
  xml_decoder.DecodeChunk(input.c_str(), input.length());
  xml_decoder.Finish();
}

scoped_ptr<loader::Decoder> Parser::ParseDocumentAsync(
    const scoped_refptr<dom::Document>& document,
    const base::SourceLocation& input_location) {
  return scoped_ptr<loader::Decoder>(new HTMLDecoder(
      document, document, NULL, dom_max_element_depth_, input_location,
      base::Closure(), error_callback_, true, require_csp_));
}

scoped_ptr<loader::Decoder> Parser::ParseXMLDocumentAsync(
    const scoped_refptr<dom::XMLDocument>& xml_document,
    const base::SourceLocation& input_location) {
  return scoped_ptr<loader::Decoder>(
      new XMLDecoder(xml_document, xml_document, NULL, dom_max_element_depth_,
                     input_location, base::Closure(), error_callback_));
}

void Parser::ErrorCallback(const std::string& error) {
  LOG(ERROR) << "Error in DOM parsing: " << error;
}

}  // namespace dom_parser
}  // namespace cobalt
