/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SampleCode.h"
#include "SkCanvas.h"
#include "SkLightingShader.h"
#include "SkNormalSource.h"
#include "sk_tool_utils.h"

class ParentControl;

// Abstract base class for all components that a control panel must have
class Control : public SkRefCnt {
public:
    Control(SkString name)
        : fName(name)
        , fParent(nullptr)
        , fRelativePos(SkPoint::Make(0.0f, 0.0f)) {}

    // Use this to propagate a click's position down to a control. Gets modulated by the component's
    // relative position
    bool click(const SkPoint& clickPos) {
        SkPoint relativeClickPos = SkPoint::Make(clickPos.fX - fRelativePos.fX,
                                                 clickPos.fY - fRelativePos.fY);
        return this->onClick(relativeClickPos);
    }

    // Use this to draw the control and its appropriate children. Gets modulated by the component's
    // relative position.
    void drawContent(SkCanvas *canvas) {
        canvas->save();
        canvas->translate(fRelativePos.fX, fRelativePos.fY);
        this->onDrawContent(canvas);
        canvas->restore();
    }

    /* Returns true when click position argumend lands over a control region in this control. Click
     * position gets modulated by the component's relative position.
     *
     * @param click The position of the click in the coordinate space relative to the parent
     */
    bool isInCtrlRegion(const SkPoint& click) {
        SkPoint relativeClickPos = SkPoint::Make(click.fX - fRelativePos.fX,
                                                 click.fY - fRelativePos.fY);
        return this->onIsInCtrlRegion(relativeClickPos);
    }

    // Returns height of content drawn
    virtual SkScalar height() const = 0;

    // Sets the parent of this component. May only be used once. Height must remain constant after
    // parent is set.
    void setParent(ParentControl *parent, const SkPoint& relativePos) {
        SkASSERT(parent);
        SkASSERT(!fParent); // No chidren transfer since relativeY would get invalid for younger kid

        fParent = parent;
        fRelativePos = relativePos;
        this->onSetParent();
    }

    // Overriden by sub-classes that need to recompute fields after parent is set. Called after
    // setting fParent.
    virtual void onSetParent() {}

    // Overriden by sub-classes that need to know when a click is released.
    virtual void onClickRelease() {}

protected:

    // Draws a label for the component, using its name and a passed value. Does NOT modulate by
    // relative height, expects CTM to have been adjusted in advance.
    void drawLabel(SkCanvas *canvas, const SkString& valueStr) const {
        // TODO Cache this
        sk_sp<SkTypeface> fLabelTypeface =
                sk_tool_utils::create_portable_typeface("sans-serif", SkFontStyle());

        SkString label;
        label.append(fName);
        label.append(": ");
        label.append(valueStr);

        SkPaint labelPaint;
        labelPaint.setTypeface(fLabelTypeface);
        labelPaint.setAntiAlias(true);
        labelPaint.setColor(0xFFFFFFFF);
        labelPaint.setTextSize(12.0f);

        canvas->drawText(label.c_str(), label.size(), 0, kLabelHeight - 6.0f, labelPaint);
    }

    SkString fName;
    ParentControl* fParent;

    static constexpr SkScalar kLabelHeight = 20.0f;

private:
    // Overriden by sub-class to draw component. Do not call directly, drawContent() modulates by
    // relative position.
    virtual void onDrawContent(SkCanvas *canvas) = 0;

    // Overriden by sub-class to handle clicks. Do not call directly, click() modulates by relative
    // position. Return true if holding mouse capture
    virtual bool onClick(const SkPoint& clickPos) { return false; }

    // Overriden by sub-classes with controls. Should return true if clickPos lands inside a control
    // region, to enable mouse caputre.
    virtual bool onIsInCtrlRegion(const SkPoint& clickPos) const { return false; }

    // The position of the control relative to it's parent
    SkPoint fRelativePos;
};

class ParentControl : public Control { // Interface for all controls that have children
public:
    ParentControl(const SkString& name) : INHERITED(name) {}

    // Adds a child
    virtual void add(sk_sp<Control> control) = 0;

    // Returns the control's width. Used to propagate width down to components that don't specify it
    virtual SkScalar width() const = 0;

private:
    typedef Control INHERITED;
};

class ControlPanel : public ParentControl {
public:

    ControlPanel(SkScalar width)
        : ParentControl(SkString("ControlPanel"))
        , fWidth(width)
        , fHeight(0.0f)
        , fSelectedControl(-1) {}

    // Width unspecified, expectation is inheritance from parent
    ControlPanel() : ControlPanel(-1.0f) {}

    // Use this for introducing clicks on a ControlPanel from outside of the framework. It
    // propagates click release or position down the chain. Returns false when click capture is
    // being released.
    bool inClick(SkView::Click *inClick) {
        if (SkView::Click::State::kUp_State == inClick->fState) {
            this->onClickRelease();
            return false;
        }
        return this->click(inClick->fCurr);
    }

    // Add children
    void add(sk_sp<Control> control) override {
        SkASSERT(!fParent); // Validity of parent's relativeY and fHeight depends on immutability
        fControls.push_back(control);
        control->setParent(this, SkPoint::Make(0.0f, fHeight));
        fHeight += control->height();
    }

    SkScalar width() const override {
        return fParent ? fParent->width() : fWidth; // Width inherited from parent if there is one
    }

    SkScalar height() const override {
        return fHeight;
    }

    // Propagate click release to selected control, deselect control
    void onClickRelease() override {
        if (fSelectedControl >= 0) {
            fControls[fSelectedControl]->onClickRelease();
        }
        fSelectedControl = -1;
    }

    // Propagate onSetParent() down to children, some might need fParent->width() refresh
    void onSetParent() override {
        for (int i = 0; i < fControls.count(); i++) {
            fControls[i]->onSetParent();
        }
    }

    // Holds a vertical shelf of controls. Can't be hierarchy root if not given a width value.
    static sk_sp<ParentControl> Make() {
        return sk_sp<ParentControl>(new ControlPanel());
    }

    // Holds a vertical shelf of controls. Only control that can be hooked from outside the
    // framework.
    static sk_sp<ParentControl> Make(SkScalar width) {
        return sk_sp<ParentControl>(new ControlPanel(width));
    }

protected:
    // Returns true if control panel has mouse captured, false when it is ready to release
    // capture
    bool onClick(const SkPoint& click) override {

        if (fSelectedControl == -1) { // If no child control selected, check every child
            for (int i = 0; i < fControls.count(); i++) {
                if (fControls[i]->isInCtrlRegion(click)) {
                    fSelectedControl = i;
                    break;
                }
            }
        }

        if (fSelectedControl >= 0) { // If child control selected, propagate click
            bool keepSelection = fControls[fSelectedControl]->click(click);
            if (!keepSelection) {
                fSelectedControl = -1;
            }
            return keepSelection;
        }

        return false;
    }

    // Draw all children
    void onDrawContent(SkCanvas* canvas) override {
        canvas->save();
        for (int i = 0; i < fControls.count(); i++) {
            fControls[i]->drawContent(canvas);
        }
        canvas->restore();
    }

    // Check all children's control regions
    bool onIsInCtrlRegion(const SkPoint& clickPos) const override {
        for (int i = 0; i < fControls.count(); i++) {
            if (fControls[i]->isInCtrlRegion(clickPos)) {
                return true;
            }
        }

        return false;
    }

private:
    SkScalar fWidth;
    SkScalar fHeight;

    SkTArray<sk_sp<Control>> fControls;
    int fSelectedControl;
};

class DiscreteSliderControl : public Control {
public:
    SkScalar height() const override {
        return 2.0f * kLabelHeight;
    }

    // Set width-dependant variables when new parent is set
    void onSetParent() override {
        fCtrlRegion = SkRect::MakeXYWH(0.0f, kLabelHeight, fParent->width(), kSliderHeight);
        fSliderRange = fParent->width() - kSliderWidth;
    }

    /* Make a slider for an integer value. Snaps to discrete positions.
     *
     * @params name    The name of the control, displayed in the label
     * @params output  Pointer to the integer that will be set by the slider
     * @params min     Min value for output.
     * @params max     Max value for output.
     */
    static sk_sp<Control> Make(SkString name, int* output, int min, int max) {
        return sk_sp<Control>(new DiscreteSliderControl(name, output, min, max));
    }

protected:
    void onDrawContent(SkCanvas* canvas) override {
        SkASSERT(fParent);
        int numChoices = fMax - fMin + 1;
        fSlider.offsetTo(fSliderRange * ( (*fOutput)/SkIntToScalar(numChoices)
                                          + 1.0f/(2.0f * numChoices) ),
                         fSlider.fTop);

        SkString valueStr;
        valueStr.appendS32(*fOutput);
        this->drawLabel(canvas, valueStr);

        SkPaint sliderPaint;
        sliderPaint.setColor(0xFFF3F3F3);
        canvas->drawRect(fSlider, sliderPaint);

        SkPaint ctrlRegionPaint;
        ctrlRegionPaint.setColor(0xFFFFFFFF);
        ctrlRegionPaint.setStyle(SkPaint::kStroke_Style);
        ctrlRegionPaint.setStrokeWidth(2.0f);
        canvas->drawRect(fCtrlRegion, ctrlRegionPaint);
    }

    bool onClick(const SkPoint& clickPos) override {
        SkASSERT(fParent);
        SkScalar x = SkScalarPin(clickPos.fX, 0.0f, fSliderRange);
        int numChoices = fMax - fMin + 1;
        *fOutput = SkTMin(SkScalarFloorToInt(numChoices * x / fSliderRange) + fMin, fMax);

        return true;
    }

    bool onIsInCtrlRegion(const SkPoint& clickPos) const override {
        SkASSERT(fParent);
        return fCtrlRegion.contains(SkRect::MakeXYWH(clickPos.fX, clickPos.fY, 1, 1));
    }

private:
    DiscreteSliderControl(SkString name, int* output, int min, int max)
            : INHERITED(name)
            , fOutput(output)
            , fMin(min)
            , fMax(max) {
        fSlider = SkRect::MakeXYWH(0, kLabelHeight, kSliderWidth, kSliderHeight);
    }

    int* fOutput;
    int fMin;
    int fMax;
    SkRect fSlider; // The rectangle that slides
    // The region in which the rectangle slides. Also the region in which mouse is caputred
    SkRect fCtrlRegion;
    SkScalar fSliderRange; // The width in pixels over which the slider can slide

    static constexpr SkScalar kSliderHeight = 20.0f;
    static constexpr SkScalar kSliderWidth = 10.0f;

    typedef Control INHERITED;
};

class ControlSwitcher : public ParentControl {
public:
    // Add children
    void add(sk_sp<Control> control) override {
        SkASSERT(!fParent); // Validity of parent's relativeY and fHeight depends on immutability
        fControls.push_back(control);
        control->setParent(this, SkPoint::Make(0.0f, kSelectorHeight));
        fHeight = SkMaxScalar(fHeight, control->height()); // Setting height to max child height.
    }

    SkScalar width() const override { return fParent ? (fParent->width()) : 0; }

    SkScalar height() const override {
        return fHeight;
    }

    // Propagate onClickRelease to control that currently captures mouse
    void onClickRelease() override {
        if (fCtrlOnClick) {
            fCtrlOnClick->onClickRelease();
        }
        fCtrlOnClick = nullptr;
    }

    void onSetParent() override {
        for (int i = 0; i < fControls.count(); i++) {
            fControls[i]->onSetParent(); // Propagate to children
        }

        // Finalize control selector
        // TODO can be moved to constructor if list-initialized
        if (!finalizedChildren) {
            fControlSelector = DiscreteSliderControl::Make(
                    SkString(fName), &fSelectedControl, 0, fControls.count()-1);
            fControlSelector->setParent(this, SkPoint::Make(0.0f, 0.0f));
            fHeight += kSelectorHeight;

            SkASSERT(fControlSelector->height() <= kSelectorHeight);
        }
    }

    /* A set of a selector and a list of controls. Displays the control from the list of controls
     * with the index set by the aforementioned selector.
     *
     * @param name The name of the switcher. Will be displayed in the selector's label.
     */
    static sk_sp<ParentControl> Make(const SkString& name) {
        return sk_sp<ParentControl>(new ControlSwitcher(name));
    }

protected:
    // Draw selector and currently selected control
    void onDrawContent(SkCanvas* canvas) override {
        fControlSelector->drawContent(canvas);
        fControls[fSelectedControl]->drawContent(canvas);
    }

    // Returns true if control panel has mouse captured, false when it is ready to release
    // capture
    bool onClick(const SkPoint& click) override {
        if (!fCtrlOnClick) {
            if (fControlSelector->isInCtrlRegion(click)) {
                fCtrlOnClick = fControlSelector.get();
            } else if (fControls[fSelectedControl]->isInCtrlRegion(click)) {
                fCtrlOnClick = fControls[fSelectedControl].get();
            }
        }
        if (fCtrlOnClick) {
            return fCtrlOnClick->click(click);
        }

        return false;
    }

    // Is in control region of selector or currently selected control
    bool onIsInCtrlRegion(const SkPoint& clickPos) const override {
        if (fControlSelector->isInCtrlRegion(clickPos)) {
            return true;
        }
        if (fControls[fSelectedControl]->isInCtrlRegion(clickPos)) {
            return true;
        }

        return false;
    }

private:
    ControlSwitcher(const SkString& name)
        : INHERITED(name)
        , fHeight(0.0)
        , fSelectedControl(0)
        , fCtrlOnClick(nullptr){}

    bool finalizedChildren = false;

    sk_sp<Control> fControlSelector;
    SkScalar fHeight;
    SkTArray<sk_sp<Control>> fControls;
    int fSelectedControl;

    Control* fCtrlOnClick;

    static constexpr SkScalar kSelectorHeight = 40.0f;

    typedef ParentControl INHERITED;
};

class ContinuousSliderControl : public Control {
public:
    SkScalar height() const override {
        return 2.0f * kLabelHeight;
    }

    void onSetParent() override {
        fSlider = SkRect::MakeXYWH(0, kLabelHeight, kSliderWidth, kSliderHeight);
        fCtrlRegion = SkRect::MakeXYWH(0.0f, kLabelHeight, fParent->width(), kSliderHeight);
        fSliderRange = fParent->width() - kSliderWidth;
    }

    /* Make a slider for an SkScalar.
     *
     * @params name    The name of the control, displayed in the label
     * @params output  Pointer to the SkScalar that will be set by the slider
     * @params min     Min value for output
     * @params max     Max value for output
     */
    static sk_sp<Control> Make(const SkString& name, SkScalar* output, SkScalar min, SkScalar max) {
       return sk_sp<Control>(new ContinuousSliderControl(name, output, min, max));
    }

protected:
    void onDrawContent(SkCanvas* canvas) override {
        SkASSERT(fParent);
        SkScalar x = fSliderRange * (*fOutput - fMin) / (fMax - fMin);
        fSlider.offsetTo(SkScalarPin(x, 0.0f, fSliderRange), fSlider.fTop);

        SkString valueStr;
        valueStr.appendScalar(*fOutput);
        this->drawLabel(canvas, valueStr);

        SkPaint sliderPaint;
        sliderPaint.setColor(0xFFF3F3F3);
        canvas->drawRect(fSlider, sliderPaint);

        SkPaint ctrlRegionPaint;
        ctrlRegionPaint.setColor(0xFFFFFFFF);
        ctrlRegionPaint.setStyle(SkPaint::kStroke_Style);
        ctrlRegionPaint.setStrokeWidth(2.0f);
        canvas->drawRect(fCtrlRegion, ctrlRegionPaint);
    }

    bool onClick(const SkPoint& clickPos) override {
        SkASSERT(fParent);
        SkScalar x = SkScalarPin(clickPos.fX, 0.0f, fSliderRange);
        *fOutput = (x/fSliderRange) * (fMax - fMin) + fMin;
        return true;
    }

    bool onIsInCtrlRegion(const SkPoint& clickPos) const override {
        SkASSERT(fParent);
        return fCtrlRegion.contains(SkRect::MakeXYWH(clickPos.fX, clickPos.fY, 1, 1));
    }

private:
    ContinuousSliderControl(const SkString& name, SkScalar* output, SkScalar min, SkScalar max)
            : INHERITED(name)
            , fOutput(output)
            , fMin(min)
            , fMax(max) {}

    SkScalar* fOutput;
    SkScalar fMin;
    SkScalar fMax;
    SkRect fSlider;
    SkRect fCtrlRegion;
    SkScalar fSliderRange;

    static constexpr SkScalar kSliderHeight = 20.0f;
    static constexpr SkScalar kSliderWidth = 10.0f;

    typedef Control INHERITED;
};

class RadialDirectionControl : public Control {
public:
    SkScalar height() const override {
        return kLabelHeight + 2.0f * kRegionRadius;
    }

    /* Make a direction selector.
     *
     * @params name    The name of the control, displayed in the label
     * @params output  Pointer to the SkVector that will be set by the slider
     */
    static sk_sp<Control> Make(const SkString& name, SkVector* output) {
        return sk_sp<Control>(new RadialDirectionControl(name, output));
    }

protected:
    void onDrawContent(SkCanvas* canvas) override {
        SkASSERT(fParent);

        SkString valueStr;
        valueStr.appendf("%.2f, %.2f", fOutput->fX, fOutput->fY);
        this->drawLabel(canvas, valueStr);

        SkPoint lineEnd = SkPoint::Make(fCtrlRegion.centerX(), fCtrlRegion.centerY())
                          + (*fOutput * (kRegionRadius - kCapRadius));
        SkPaint linePaint;
        linePaint.setColor(0xFFF3F3F3);
        linePaint.setStrokeWidth(kStrokeWidth);
        linePaint.setAntiAlias(true);
        linePaint.setStrokeCap(SkPaint::kRound_Cap);
        canvas->drawLine(fCtrlRegion.centerX(), fCtrlRegion.centerY(),
                         lineEnd.fX, lineEnd.fY, linePaint);

        SkPaint ctrlRegionPaint;
        ctrlRegionPaint.setColor(0xFFFFFFFF);
        ctrlRegionPaint.setStyle(SkPaint::kStroke_Style);
        ctrlRegionPaint.setStrokeWidth(2.0f);
        ctrlRegionPaint.setAntiAlias(true);
        canvas->drawCircle(fCtrlRegion.centerX(), fCtrlRegion.centerY(), kRegionRadius,
                           ctrlRegionPaint);
    }

    bool onClick(const SkPoint& clickPos) override {
        SkASSERT(fParent);
        fOutput->fX = clickPos.fX - fCtrlRegion.centerX();
        fOutput->fY = clickPos.fY - fCtrlRegion.centerY();
        fOutput->normalize();

        return true;
    }

    bool onIsInCtrlRegion(const SkPoint& clickPos) const override {
        SkASSERT(fParent);
        return fCtrlRegion.contains(SkRect::MakeXYWH(clickPos.fX, clickPos.fY,
                                                     1, 1));
    }

private:
    RadialDirectionControl(const SkString& name, SkVector* output)
            : INHERITED(name)
            , fOutput(output) {
        fCtrlRegion = SkRect::MakeXYWH(0.0f, kLabelHeight,
                                       kRegionRadius * 2.0f, kRegionRadius * 2.0f);
    }

    SkVector* fOutput;
    SkRect fCtrlRegion;

    static constexpr SkScalar kRegionRadius = 50.0f;
    static constexpr SkScalar kStrokeWidth = 6.0f;
    static constexpr SkScalar kCapRadius = kStrokeWidth / 2.0f;

    typedef Control INHERITED;
};

class ColorDisplay: public Control {
public:
    SkScalar height() const override {
        return kHeight;
    }

    void onSetParent() override {
        fDisplayRect = SkRect::MakeXYWH(0.0f, kPadding, fParent->width(), kHeight - kPadding);
    }

    /* Make a display that shows an SkColor3f.
     *
     * @params output  Pointer to the SkColor3f that will be displayed
     */
    static sk_sp<Control> Make(SkColor3f* input) {
        return sk_sp<Control>(new ColorDisplay(SkString("ColorDisplay"), input));
    }

protected:
    void onDrawContent(SkCanvas* canvas) override {
        SkASSERT(fParent);

        SkPaint displayPaint;
        displayPaint.setColor(SkColor4f::FromColor3f(*fInput, 1.0f).toSkColor());
        canvas->drawRect(fDisplayRect, displayPaint);
    }

private:
    ColorDisplay(const SkString& name, SkColor3f* input)
            : INHERITED(name)
            , fInput(input) {}

    SkColor3f* fInput;
    SkRect fDisplayRect;

    static constexpr SkScalar kHeight = 24.0f;
    static constexpr SkScalar kPadding = 4.0f;

    typedef Control INHERITED;
};

class BevelView : public SampleView {
public:
    BevelView()
        : fShapeBounds(SkRect::MakeWH(kShapeBoundsSize, kShapeBoundsSize))
        , fControlPanel(kCtrlRange) {
        this->setBGColor(0xFF666868); // Slightly colorized gray for contrast

        // Controls
        fBevelWidth = 25.0f;
        fBevelHeight = 25.0f;
        fBevelType = 0;

        int currLight = 0;
        fLightDefs[currLight++] =
                {SkVector::Make(0.0f, 1.0f), 1.0f, SkColor3f::Make(0.6f, 0.45f, 0.3f)};
        fLightDefs[currLight++] =
                {SkVector::Make(0.0f, -1.0f), 1.0f, SkColor3f::Make(0.3f, 0.45f, 0.6f)};
        fLightDefs[currLight++] =
                {SkVector::Make(1.0f, 0.0f), 1.0f, SkColor3f::Make(0.0f, 0.0f, 0.0f)};
        // Making sure we initialized all lights
        SkASSERT(currLight == kNumLights);

        fControlPanel.add(ContinuousSliderControl::Make(SkString("BevelWidth"), &fBevelWidth,
                                                        1.0f, kShapeBoundsSize));
        fControlPanel.add(ContinuousSliderControl::Make(SkString("BevelHeight"), &fBevelHeight,
                                                        -50.0f, 50.0f));
        fControlPanel.add(DiscreteSliderControl::Make(SkString("BevelType"), &fBevelType,
                                                      0, 2));
        sk_sp<ParentControl> lightCtrlSelector = ControlSwitcher::Make(SkString("SelectedLight"));
        for (int i = 0; i < kNumLights; i++) {
            SkString name("Light");
            name.appendS32(i);
            sk_sp<ParentControl> currLightPanel = ControlPanel::Make();
            SkString dirName(name);
            dirName.append("Dir");
            currLightPanel->add(RadialDirectionControl::Make(dirName, &(fLightDefs[i].fDirXY)));
            SkString heightName(name);
            heightName.append("Height");
            currLightPanel->add(ContinuousSliderControl::Make(heightName, &(fLightDefs[i].fDirZ),
                                                             0.0f, 2.0f));
            SkString redName(name);
            redName.append("Red");
            currLightPanel->add(ContinuousSliderControl::Make(redName, &(fLightDefs[i].fColor.fX),
                                                              0.0f, 1.0f));
            SkString greenName(name);
            greenName.append("Green");
            currLightPanel->add(ContinuousSliderControl::Make(greenName, &(fLightDefs[i].fColor.fY),
                                                              0.0f, 1.0f));
            SkString blueName(name);
            blueName.append("Blue");
            currLightPanel->add(ContinuousSliderControl::Make(blueName, &(fLightDefs[i].fColor.fZ),
                                                              0.0f, 1.0f));
            currLightPanel->add(ColorDisplay::Make(&(fLightDefs[i].fColor)));
            lightCtrlSelector->add(currLightPanel);
        }
        fControlPanel.add(lightCtrlSelector);

        fControlPanelSelected = false;
        fDirtyNormalSource = true;

        fLabelTypeface = sk_tool_utils::create_portable_typeface("sans-serif", SkFontStyle());
    }

protected:
    bool onQuery(SkEvent *evt) override {
        if (SampleCode::TitleQ(*evt)) {
            SampleCode::TitleR(evt, "Bevel");
            return true;
        }

        return this->INHERITED::onQuery(evt);
    }

    enum Shape {
        kCircle_Shape,
        kRect_Shape,
    };
    void drawShape(enum Shape shape, SkCanvas* canvas) {
        canvas->save();

        SkPaint paint;

        if (fDirtyNormalSource) {
            fNormalSource = SkNormalSource::MakeBevel((SkNormalSource::BevelType)fBevelType,
                                                      fBevelWidth, fBevelHeight);
            fDirtyNormalSource = false;
        }

        paint.setShader(SkLightingShader::Make(nullptr, fNormalSource, fLights));
        paint.setAntiAlias(true);
        paint.setColor(0xFFDDDDDD);
        switch (shape) {
            case kCircle_Shape:
                canvas->drawCircle(fShapeBounds.centerX(), fShapeBounds.centerY(),
                                   fShapeBounds.width()/2.0f, paint);
                break;
            case kRect_Shape:
                canvas->drawRect(fShapeBounds, paint);
                break;
            default:
                SkDEBUGFAIL("Invalid shape enum for drawShape");
        }

        canvas->restore();
    }

    void onDrawContent(SkCanvas *canvas) override {

        canvas->save();
        canvas->resetMatrix(); // Force static control panel position
        fControlPanel.drawContent(canvas);
        canvas->restore();

        SkLights::Builder builder;
        for (int i = 0; i < kNumLights; i++) {
            builder.add(SkLights::Light::MakeDirectional(fLightDefs[i].fColor,
                                                         SkPoint3::Make(fLightDefs[i].fDirXY.fX,
                                                                        fLightDefs[i].fDirXY.fY,
                                                                        fLightDefs[i].fDirZ)));
        }
        builder.setAmbientLightColor(SkColor3f::Make(0.4f, 0.4f, 0.4f));
        fLights = builder.finish();

        // Draw shapes
        SkScalar xPos = kCtrlRange + 25.0f;
        SkScalar yPos = fShapeBounds.height();
        for (Shape shape : { kCircle_Shape, kRect_Shape }) {
            canvas->save();
            canvas->translate(xPos, yPos);
            this->drawShape(shape, canvas);
            canvas->restore();

            xPos += 1.2f * fShapeBounds.width();
        }
    }

    SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
        return new SkView::Click(this);
    }

    bool onClick(Click *click) override {
        // Control panel mouse handling
        fControlPanelSelected = fControlPanel.inClick(click);

        if (fControlPanelSelected) { // Control modification
            fDirtyNormalSource = true;

            this->inval(nullptr);
            return true;
        }

        // TODO move shapes
        this->inval(nullptr);
        return true;
    }

private:
    static constexpr int kNumTestRects = 3;

    static constexpr SkScalar kShapeBoundsSize = 120.0f;

    static constexpr SkScalar kCtrlRange = 150.0f;

    static constexpr int kNumLights = 3;

    const SkRect fShapeBounds;

    SkScalar fBevelWidth;
    SkScalar fBevelHeight;
    int      fBevelType;

    sk_sp<SkNormalSource> fNormalSource;
    bool fDirtyNormalSource;

    sk_sp<SkLights> fLights;

    struct LightDef {
        SkVector fDirXY;
        SkScalar fDirZ;
        SkColor3f fColor;

        LightDef() {}
        LightDef(SkVector dirXY, SkScalar dirZ, SkColor3f color)
            : fDirXY(dirXY)
            , fDirZ(dirZ)
            , fColor(color) {}
    };
    LightDef fLightDefs[kNumLights];

    ControlPanel fControlPanel;
    bool fControlPanelSelected;

    sk_sp<SkTypeface> fLabelTypeface;

    typedef SampleView INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

static SkView* MyFactory() { return new BevelView; }
static SkViewRegister reg(MyFactory);

