/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "include/core/SkCanvas.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkRRect.h"
#include "include/private/base/SkAssert.h"
#include "src/base/SkRandom.h"
#include "tools/viewer/Slide.h"

#include <chrono>
#include <ctime>

// Implementation in C++ of Mozilla Canvas2D benchmark Canvas Clock Test
// See https://code.google.com/p/skia/issues/detail?id=1626

#define USE_PATH 1

class ClockSlide : public Slide {
public:
    ClockSlide() { fName = "Clock"; }

    void draw(SkCanvas* canvas) override {
        SkPaint paintFill;
        SkPaint paintStroke;
        SkPath  path;

        canvas->save();
        canvas->translate(150, 150);
        canvas->scale(0.4f, 0.4f);
        canvas->rotate(-180.f/2.f);

        paintFill.setAntiAlias(true);
        paintFill.setColor(SK_ColorBLACK);
        paintStroke.setAntiAlias(true);
        paintStroke.setStyle(SkPaint::kStroke_Style);
        paintStroke.setColor(SK_ColorBLACK);
        paintStroke.setStrokeWidth(8);
        paintStroke.setStrokeCap(SkPaint::kRound_Cap);

        // Hour marks
        SkRect rect;
#ifndef USE_PATH
        rect = SkRect::MakeLTRB(200-4, -4, 240+4, 4);
        SkRRect rrect;
        SkVector radii[4] = {{4,4}, {4,4}, {4,4}, {4,4}};
        rrect.setRectRadii(rect, radii);
#endif
        canvas->save();
        for (int i=0;i<12;i++){
            canvas->rotate(180.f/6.f);
#ifdef USE_PATH
            path = SkPath::Line({200,0}, {240,0});
            canvas->drawPath(path, paintStroke);
#else
            canvas->drawRRect(rrect, paintFill);
#endif
        }
        canvas->restore();

        // Minute marks
        canvas->save();
#ifdef USE_PATH
        paintStroke.setStrokeWidth(5);
#else
        rect = SkRect::MakeLTRB(231.5f, -2.5f, 242.5, 2.5f);
        radii[0] = SkPoint::Make(2.5f,2.5f);
        radii[1] = SkPoint::Make(2.5f,2.5f);
        radii[2] = SkPoint::Make(2.5f,2.5f);
        radii[3] = SkPoint::Make(2.5f,2.5f);
        rrect.setRectRadii(rect, radii);
#endif
        for (int i=0;i<60;i++){
            if (i%5 == 0) {
                canvas->rotate(180.f/30.f);
                continue;
            }
#ifdef USE_PATH
            path = SkPath::Line({234,0}, {240,0});
            canvas->drawPath(path, paintStroke);
#else
            canvas->drawRRect(rrect, paintFill);
#endif
            canvas->rotate(180.f/30.f);
        }
        canvas->restore();

        const auto  time  = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
        const auto* ltime = std::localtime(&time);  // not thread safe, but should be ok for slides

        paintFill.setColor(SK_ColorBLACK);

        // Write hours
        canvas->save();
        canvas->rotate(ltime->tm_hour * (180.f / 6) +
                       ltime->tm_min  * (180.f / 360) +
                       ltime->tm_sec  * (180.f / 21600));
#ifdef USE_PATH
        paintStroke.setStrokeWidth(14);
        path = SkPath::Line({-20,0}, {80,0});
        canvas->drawPath(path, paintStroke);
#else
        rect = SkRect::MakeLTRB(-20-7, -7, 80+7, 7);
        radii[0] = SkPoint::Make(7,7);
        radii[1] = SkPoint::Make(7,7);
        radii[2] = SkPoint::Make(7,7);
        radii[3] = SkPoint::Make(7,7);
        rrect.setRectRadii(rect, radii);
        canvas->drawRRect(rrect, paintFill);
#endif
        canvas->restore();

        // Write minutes
        canvas->save();
        canvas->rotate(ltime->tm_min * (180.f / 30) +
                       ltime->tm_sec * (180.f / 1800));
#ifdef USE_PATH
        paintStroke.setStrokeWidth(10);
        path = SkPath::Line({-56,0}, {224,0});
        canvas->drawPath(path, paintStroke);
#else
        rect = SkRect::MakeLTRB(-56-5, -5, 224+5, 5);
        radii[0] = SkPoint::Make(5,5);
        radii[1] = SkPoint::Make(5,5);
        radii[2] = SkPoint::Make(5,5);
        radii[3] = SkPoint::Make(5,5);
        rrect.setRectRadii(rect, radii);
        canvas->drawRRect(rrect, paintFill);
#endif
        canvas->restore();

        // Write seconds
        canvas->save();
        canvas->rotate(ltime->tm_sec * (180.f / 30));
        paintFill.setColor(0xffd40000);
        paintStroke.setColor(0xffd40000);
        paintStroke.setStrokeWidth(6);
#ifdef USE_PATH
        path = SkPath::Line({-60,0}, {166,0});
        canvas->drawPath(path, paintStroke);
#else
        rect = SkRect::MakeLTRB(-60-3, -3, 166+3, 3);
        radii[0] = SkPoint::Make(3,3);
        radii[1] = SkPoint::Make(3,3);
        radii[2] = SkPoint::Make(3,3);
        radii[3] = SkPoint::Make(3,3);
        rrect.setRectRadii(rect, radii);
        canvas->drawRRect(rrect, paintFill);
#endif
        rect = SkRect::MakeLTRB(-20, -20, 20, 20);
#ifdef USE_PATH
        path = SkPathBuilder()
               .arcTo(rect, 0, 0, false)
               .addOval(rect, SkPathDirection::kCCW)
               .arcTo(rect, 360, 0, true)
               .detach();
        canvas->drawPath(path, paintFill);
#else
        canvas->drawOval(rect, paintFill);
#endif
        rect = SkRect::MakeLTRB(-20+190, -20, 20+190, 20);
#ifdef USE_PATH
        path = SkPathBuilder()
               .arcTo(rect, 0, 0, false)
               .addOval(rect, SkPathDirection::kCCW)
               .arcTo(rect, 360, 0, true)
               .detach();
        canvas->drawPath(path, paintStroke);
#else
        canvas->drawOval(rect, paintStroke);
#endif
        paintFill.setColor(0xff505050);
#ifdef USE_PATH
        rect = SkRect::MakeLTRB(-6, -6, 6, 6);
        path = SkPathBuilder(path)
                .arcTo(rect, 0, 0, false)
                .addOval(rect, SkPathDirection::kCCW)
                .arcTo(rect, 360, 0, true)
                .detach();
        canvas->drawPath(path, paintFill);
#else
        canvas->drawOval(rect, paintFill);
        rect = SkRect::MakeLTRB(-6, -6, 6, 6);
        canvas->drawOval(rect, paintFill);
#endif
        canvas->restore();

        paintStroke.setStrokeWidth(18);
        paintStroke.setColor(0xff325FA2);
        rect = SkRect::MakeLTRB(-284, -284, 284, 284);
#ifdef USE_PATH
        path = SkPathBuilder()
               .arcTo(rect, 0, 0, false)
               .addOval(rect, SkPathDirection::kCCW)
               .arcTo(rect, 360, 0, true)
               .detach();
        canvas->drawPath(path, paintStroke);
#else
        canvas->drawOval(rect, paintStroke);
#endif

        canvas->restore();
    }

    bool animate(double /*nanos*/) override { return true; }
};

DEF_SLIDE( return new ClockSlide(); )
