/*
 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
 * 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 "components/ui_toggle_button.h"

#include "common/image.h"
#include "engines/gfx/gfx_engine_manager.h"
#include "imgdecode/cache_manager.h"
namespace {
constexpr int16_t TOGGLE_BTN_WIDTH = 32;
constexpr int16_t TOGGLE_BTN_CORNER_RADIUS = 11;
constexpr int16_t TOGGLE_BTN_RADIUS_DIFF = 2;
constexpr uint8_t TOGGLE_BTN_UNSELECTED_OPA = 97;
#if DEFAULT_ANIMATION
constexpr int16_t DEFAULT_ANIMATOR_TIME = 150;
constexpr float BEZIER_CONTROL_POINT_X_1 = 0.2;
constexpr float BEZIER_CONTROL_POINT_X_2 = 0.2;
#endif
} // namespace
namespace OHOS {
UIToggleButton::UIToggleButton()
    : corner_(TOGGLE_BTN_CORNER_RADIUS),
      radius_(TOGGLE_BTN_CORNER_RADIUS - TOGGLE_BTN_RADIUS_DIFF),
      rectWidth_(TOGGLE_BTN_WIDTH)
{
    backgroundOpacity_ = TOGGLE_BTN_UNSELECTED_OPA;
    image_[UNSELECTED].SetSrc("");
    image_[SELECTED].SetSrc("");
#if DEFAULT_ANIMATION
    checkBoxAnimator_.SetTime(DEFAULT_ANIMATOR_TIME);
#endif
    Resize(width_, height_);
}

void UIToggleButton::SetState(bool state)
{
    if (state) {
        UICheckBox::SetState(SELECTED);
    } else {
        UICheckBox::SetState(UNSELECTED);
    }
    Invalidate();
}

void UIToggleButton::CalculateSize()
{
    width_ = GetWidth();
    height_ = GetHeight();
    int16_t minValue = (width_ > height_) ? height_ : width_;
    corner_ = TOGGLE_BTN_CORNER_RADIUS * minValue / DEFAULT_HOT_HEIGHT;
    int16_t radiusDiff = TOGGLE_BTN_RADIUS_DIFF * minValue / DEFAULT_HOT_WIDTH;
    radius_ = corner_ - radiusDiff;
    rectWidth_ = TOGGLE_BTN_WIDTH * minValue / DEFAULT_HOT_WIDTH;

    Rect contentRect = GetContentRect();
    int16_t dx = (width_ - rectWidth_) / 2; // 2: half
    int16_t dy = (height_ / 2) - corner_;   // 2: half
    int16_t x = contentRect.GetX() + dx;
    int16_t y = contentRect.GetY() + dy;
    leftCenter_ = {static_cast<int16_t>(x + corner_), static_cast<int16_t>(y + corner_)};
    rightCenter_ = {static_cast<int16_t>(x + rectWidth_ - corner_), static_cast<int16_t>(y + corner_)};
#if DEFAULT_ANIMATION
    if (checkBoxAnimator_.GetState() != Animator::START) {
        if (IsRtl()) {
            currentCenter_ = (state_ == SELECTED) ? leftCenter_ : rightCenter_;
        } else {
            currentCenter_ = (state_ == SELECTED) ? rightCenter_ : leftCenter_;
        }
        backgroundOpacity_ = (state_ == SELECTED) ? OPA_OPAQUE : TOGGLE_BTN_UNSELECTED_OPA;
        bgColor_ = (state_ == SELECTED) ? selectedStateColor_ : Color::White();
    }
#else
    if (IsRtl()) {
        currentCenter_ = (state_ == SELECTED) ? leftCenter_ : rightCenter_;
    } else {
        currentCenter_ = (state_ == SELECTED) ? rightCenter_ : leftCenter_;
    }
    backgroundOpacity_ = (state_ == SELECTED) ? OPA_OPAQUE : TOGGLE_BTN_UNSELECTED_OPA;
    bgColor_ = (state_ == SELECTED) ? selectedStateColor_ : Color::White();
#endif
    rectMid_.SetRect(x, y, x + rectWidth_, y + (corner_ << 1) + 1);
}

void UIToggleButton::OnDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
{
    if ((image_[SELECTED].GetSrcType() != IMG_SRC_UNKNOWN) && (image_[UNSELECTED].GetSrcType() != IMG_SRC_UNKNOWN)) {
        UICheckBox::OnDraw(gfxDstBuffer, invalidatedArea);
    } else {
        CalculateSize();
        BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
        baseGfxEngine->DrawRect(gfxDstBuffer, GetRect(), invalidatedArea, *style_, opaScale_);
        Rect contentRect = GetContentRect();
        Rect trunc = invalidatedArea;
        bool isIntersect = trunc.Intersect(trunc, contentRect);
        if (!isIntersect) {
            return;
        }
        Style styleUnSelect = StyleDefault::GetBackgroundTransparentStyle();
        styleUnSelect.bgColor_ = bgColor_;
        styleUnSelect.bgOpa_ = backgroundOpacity_;
        styleUnSelect.borderRadius_ = corner_;
        baseGfxEngine->DrawRect(gfxDstBuffer, rectMid_, trunc, styleUnSelect, opaScale_);
        ArcInfo arcInfoLeft = {currentCenter_, {0}, radius_, 0, CIRCLE_IN_DEGREE, nullptr};
        styleUnSelect.lineColor_ = Color::White();
        styleUnSelect.lineWidth_ = radius_;
        baseGfxEngine->DrawArc(gfxDstBuffer, arcInfoLeft, trunc, styleUnSelect, OPA_OPAQUE,
                               CapType::CAP_NONE);
    }
}
#if DEFAULT_ANIMATION
void UIToggleButton::Callback(UIView* view)
{
    runTime_ = checkBoxAnimator_.GetRunTime();
    float x = static_cast<float>(runTime_) / checkBoxAnimator_.GetTime();
    float coefficient = Interpolation::GetBezierY(x, BEZIER_CONTROL_POINT_X_1, 0, BEZIER_CONTROL_POINT_X_2, 1);
    if (state_ == SELECTED) {
        currentCenter_.y = rightCenter_.y;
        if (IsRtl()) {
            currentCenter_.x = rightCenter_.x - static_cast<uint16_t>((rightCenter_.x - leftCenter_.x) * coefficient);
        } else {
            currentCenter_.x = static_cast<int16_t>((rightCenter_.x - leftCenter_.x) * coefficient) + leftCenter_.x;
        }
        backgroundOpacity_ =
            static_cast<uint8_t>(TOGGLE_BTN_UNSELECTED_OPA + (OPA_OPAQUE - TOGGLE_BTN_UNSELECTED_OPA) * coefficient);
        bgColor_ =
            Color::GetMixColor(selectedStateColor_, Color::White(), static_cast<uint8_t>(OPA_OPAQUE * coefficient));
    } else {
        currentCenter_.y = leftCenter_.y;
        if (IsRtl()) {
            currentCenter_.x = static_cast<int16_t>((rightCenter_.x - leftCenter_.x) * coefficient) + leftCenter_.x;
        } else {
            currentCenter_.x = rightCenter_.x - static_cast<uint16_t>((rightCenter_.x - leftCenter_.x) * coefficient);
        }
        backgroundOpacity_ = static_cast<uint8_t>(OPA_OPAQUE - (OPA_OPAQUE - TOGGLE_BTN_UNSELECTED_OPA) * coefficient);
        bgColor_ = Color::GetMixColor(selectedStateColor_, Color::White(),
                                      static_cast<uint8_t>(OPA_OPAQUE * (1 - coefficient)));
    }
    Invalidate();
}

void UIToggleButton::OnStop(UIView& view)
{
    if (state_ == SELECTED) {
        bgColor_ = selectedStateColor_;
    } else {
        bgColor_ = Color::White();
    }
    backgroundOpacity_ = (state_ == SELECTED) ? OPA_OPAQUE : TOGGLE_BTN_UNSELECTED_OPA;
    Invalidate();
}
#endif

void UIToggleButton::EnableRtl(bool isRtl)
{
    isRtl_ = isRtl;
}

bool UIToggleButton::IsRtl()
{
    return isRtl_;
}
} // namespace OHOS