/*
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#include "third_party/blink/renderer/core/html/html_progress_element.h"

#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/html/shadow/progress_shadow_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/layout_progress.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"

namespace blink {

using namespace html_names;

const double HTMLProgressElement::kIndeterminatePosition = -1;
const double HTMLProgressElement::kInvalidPosition = -2;

HTMLProgressElement::HTMLProgressElement(Document& document)
    : HTMLElement(kProgressTag, document), value_(nullptr) {
  UseCounter::Count(document, WebFeature::kProgressElement);
}

HTMLProgressElement::~HTMLProgressElement() = default;

HTMLProgressElement* HTMLProgressElement::Create(Document& document) {
  HTMLProgressElement* progress =
      MakeGarbageCollected<HTMLProgressElement>(document);
  progress->EnsureUserAgentShadowRoot();
  return progress;
}

LayoutObject* HTMLProgressElement::CreateLayoutObject(
    const ComputedStyle& style) {
  if (!style.HasAppearance()) {
    UseCounter::Count(GetDocument(),
                      WebFeature::kProgressElementWithNoneAppearance);
    return LayoutObject::CreateObject(this, style);
  }
  UseCounter::Count(GetDocument(),
                    WebFeature::kProgressElementWithProgressBarAppearance);
  return new LayoutProgress(this);
}

LayoutProgress* HTMLProgressElement::GetLayoutProgress() const {
  if (GetLayoutObject() && GetLayoutObject()->IsProgress())
    return ToLayoutProgress(GetLayoutObject());
  return nullptr;
}

void HTMLProgressElement::ParseAttribute(
    const AttributeModificationParams& params) {
  if (params.name == kValueAttr) {
    if (params.old_value.IsNull() != params.new_value.IsNull())
      PseudoStateChanged(CSSSelector::kPseudoIndeterminate);
    DidElementStateChange();
  } else if (params.name == kMaxAttr) {
    DidElementStateChange();
  } else {
    HTMLElement::ParseAttribute(params);
  }
}

void HTMLProgressElement::AttachLayoutTree(AttachContext& context) {
  HTMLElement::AttachLayoutTree(context);
  if (LayoutProgress* layout_progress = GetLayoutProgress())
    layout_progress->UpdateFromElement();
}

double HTMLProgressElement::value() const {
  double value = GetFloatingPointAttribute(kValueAttr);
  // Otherwise, if the parsed value was greater than or equal to the maximum
  // value, then the current value of the progress bar is the maximum value
  // of the progress bar. Otherwise, if parsing the value attribute's value
  // resulted in an error, or a number less than or equal to zero, then the
  // current value of the progress bar is zero.
  return !std::isfinite(value) || value < 0 ? 0 : std::min(value, max());
}

void HTMLProgressElement::setValue(double value) {
  SetFloatingPointAttribute(kValueAttr, std::max(value, 0.));
}

double HTMLProgressElement::max() const {
  double max = GetFloatingPointAttribute(kMaxAttr);
  // Otherwise, if the element has no max attribute, or if it has one but
  // parsing it resulted in an error, or if the parsed value was less than or
  // equal to zero, then the maximum value of the progress bar is 1.0.
  return !std::isfinite(max) || max <= 0 ? 1 : max;
}

void HTMLProgressElement::setMax(double max) {
  // FIXME: The specification says we should ignore the input value if it is
  // inferior or equal to 0.
  SetFloatingPointAttribute(kMaxAttr, max > 0 ? max : 1);
}

double HTMLProgressElement::position() const {
  if (!IsDeterminate())
    return HTMLProgressElement::kIndeterminatePosition;
  return value() / max();
}

bool HTMLProgressElement::IsDeterminate() const {
  return FastHasAttribute(kValueAttr);
}

void HTMLProgressElement::DidElementStateChange() {
  SetValueWidthPercentage(position() * 100);
  if (LayoutProgress* layout_progress = GetLayoutProgress())
    layout_progress->UpdateFromElement();
}

void HTMLProgressElement::DidAddUserAgentShadowRoot(ShadowRoot& root) {
  DCHECK(!value_);

  ProgressShadowElement* inner = ProgressShadowElement::Create(GetDocument());
  inner->SetShadowPseudoId(AtomicString("-webkit-progress-inner-element"));
  root.AppendChild(inner);

  ProgressShadowElement* bar = ProgressShadowElement::Create(GetDocument());
  bar->SetShadowPseudoId(AtomicString("-webkit-progress-bar"));
  value_ = ProgressShadowElement::Create(GetDocument());
  value_->SetShadowPseudoId(AtomicString("-webkit-progress-value"));
  SetValueWidthPercentage(HTMLProgressElement::kIndeterminatePosition * 100);
  bar->AppendChild(value_);

  inner->AppendChild(bar);
}

bool HTMLProgressElement::ShouldAppearIndeterminate() const {
  return !IsDeterminate();
}

void HTMLProgressElement::Trace(Visitor* visitor) {
  visitor->Trace(value_);
  HTMLElement::Trace(visitor);
}

void HTMLProgressElement::SetValueWidthPercentage(double width) const {
  value_->SetInlineStyleProperty(CSSPropertyWidth, width,
                                 CSSPrimitiveValue::UnitType::kPercentage);
}

}  // namespace blink
