/*
 * Copyright (C) 2011 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "core/editing/markers/DocumentMarker.h"

#include "wtf/StdLibExtras.h"

namespace blink {

DocumentMarkerDetails::~DocumentMarkerDetails() {}

class DocumentMarkerDescription final : public DocumentMarkerDetails {
 public:
  static DocumentMarkerDescription* create(const String&);

  const String& description() const { return m_description; }
  bool isDescription() const override { return true; }

 private:
  explicit DocumentMarkerDescription(const String& description)
      : m_description(description) {}

  String m_description;
};

DocumentMarkerDescription* DocumentMarkerDescription::create(
    const String& description) {
  return new DocumentMarkerDescription(description);
}

inline DocumentMarkerDescription* toDocumentMarkerDescription(
    DocumentMarkerDetails* details) {
  if (details && details->isDescription())
    return static_cast<DocumentMarkerDescription*>(details);
  return 0;
}

class DocumentMarkerTextMatch final : public DocumentMarkerDetails {
 public:
  static DocumentMarkerTextMatch* create(bool);

  bool IsActiveMatch() const { return m_match; }

  bool isTextMatch() const override { return true; }

 private:
  explicit DocumentMarkerTextMatch(bool match) : m_match(match) {}

  bool m_match;
};

DocumentMarkerTextMatch* DocumentMarkerTextMatch::create(bool match) {
  DEFINE_STATIC_LOCAL(DocumentMarkerTextMatch, trueInstance,
                      (new DocumentMarkerTextMatch(true)));
  DEFINE_STATIC_LOCAL(DocumentMarkerTextMatch, falseInstance,
                      (new DocumentMarkerTextMatch(false)));
  return match ? &trueInstance : &falseInstance;
}

inline DocumentMarkerTextMatch* toDocumentMarkerTextMatch(
    DocumentMarkerDetails* details) {
  if (details && details->isTextMatch())
    return static_cast<DocumentMarkerTextMatch*>(details);
  return 0;
}

class TextCompositionMarkerDetails final : public DocumentMarkerDetails {
 public:
  static TextCompositionMarkerDetails* create(Color underlineColor,
                                              bool thick,
                                              Color backgroundColor);

  bool isComposition() const override { return true; }
  Color underlineColor() const { return m_underlineColor; }
  bool thick() const { return m_thick; }
  Color backgroundColor() const { return m_backgroundColor; }

 private:
  TextCompositionMarkerDetails(Color underlineColor,
                               bool thick,
                               Color backgroundColor)
      : m_underlineColor(underlineColor),
        m_backgroundColor(backgroundColor),
        m_thick(thick) {}

  Color m_underlineColor;
  Color m_backgroundColor;
  bool m_thick;
};

TextCompositionMarkerDetails* TextCompositionMarkerDetails::create(
    Color underlineColor,
    bool thick,
    Color backgroundColor) {
  return new TextCompositionMarkerDetails(underlineColor, thick,
                                          backgroundColor);
}

inline TextCompositionMarkerDetails* toTextCompositionMarkerDetails(
    DocumentMarkerDetails* details) {
  if (details && details->isComposition())
    return static_cast<TextCompositionMarkerDetails*>(details);
  return nullptr;
}

DocumentMarker::DocumentMarker(MarkerType type,
                               unsigned startOffset,
                               unsigned endOffset,
                               const String& description)
    : m_type(type),
      m_startOffset(startOffset),
      m_endOffset(endOffset),
      m_details(description.isEmpty()
                    ? nullptr
                    : DocumentMarkerDescription::create(description)) {}

DocumentMarker::DocumentMarker(unsigned startOffset,
                               unsigned endOffset,
                               bool activeMatch)
    : m_type(DocumentMarker::TextMatch),
      m_startOffset(startOffset),
      m_endOffset(endOffset),
      m_details(DocumentMarkerTextMatch::create(activeMatch)) {}

DocumentMarker::DocumentMarker(unsigned startOffset,
                               unsigned endOffset,
                               Color underlineColor,
                               bool thick,
                               Color backgroundColor)
    : m_type(DocumentMarker::Composition),
      m_startOffset(startOffset),
      m_endOffset(endOffset),
      m_details(TextCompositionMarkerDetails::create(underlineColor,
                                                     thick,
                                                     backgroundColor)) {}

DocumentMarker::DocumentMarker(const DocumentMarker& marker)
    : m_type(marker.type()),
      m_startOffset(marker.startOffset()),
      m_endOffset(marker.endOffset()),
      m_details(marker.details()) {}

void DocumentMarker::shiftOffsets(int delta) {
  m_startOffset += delta;
  m_endOffset += delta;
}

void DocumentMarker::setIsActiveMatch(bool active) {
  m_details = DocumentMarkerTextMatch::create(active);
}

const String& DocumentMarker::description() const {
  if (DocumentMarkerDescription* details =
          toDocumentMarkerDescription(m_details.get()))
    return details->description();
  return emptyString;
}

bool DocumentMarker::IsActiveMatch() const {
  if (DocumentMarkerTextMatch* details =
          toDocumentMarkerTextMatch(m_details.get()))
    return details->IsActiveMatch();
  return false;
}

Color DocumentMarker::underlineColor() const {
  if (TextCompositionMarkerDetails* details =
          toTextCompositionMarkerDetails(m_details.get()))
    return details->underlineColor();
  return Color::transparent;
}

bool DocumentMarker::thick() const {
  if (TextCompositionMarkerDetails* details =
          toTextCompositionMarkerDetails(m_details.get()))
    return details->thick();
  return false;
}

Color DocumentMarker::backgroundColor() const {
  if (TextCompositionMarkerDetails* details =
          toTextCompositionMarkerDetails(m_details.get()))
    return details->backgroundColor();
  return Color::transparent;
}

DEFINE_TRACE(DocumentMarker) {
  visitor->trace(m_details);
}

}  // namespace blink
