/*
 * 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);

