/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "TransitionView.h"

#include "OverView.h"
#include "SampleCode.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkTime.h"
#include "SkInterpolator.h"

static const char gIsTransitionQuery[] = "is-transition";
static const char gReplaceTransitionEvt[] = "replace-transition-view";

bool is_transition(SkView* view) {
    SkEvent isTransition(gIsTransitionQuery);
    return view->doQuery(&isTransition);
}

class TransitionView : public SampleView {
    enum {
        // kDurationMS = 500
        kDurationMS = 1
    };

public:
    TransitionView(SkView* prev, SkView* next, int direction) : fInterp(4, 2){
        fAnimationDirection = (Direction)(1 << (direction % 8));

        fPrev = prev;
        fPrev->setClipToBounds(false);
        fPrev->setVisibleP(true);
        (void)SampleView::SetUsePipe(fPrev, SkOSMenu::kOffState);
        //Not calling unref because fPrev is assumed to have been created, so
        //this will result in a transfer of ownership
        this->attachChildToBack(fPrev);

        fNext = next;
        fNext->setClipToBounds(true);
        fNext->setVisibleP(true);
        (void)SampleView::SetUsePipe(fNext, SkOSMenu::kOffState);
        //Calling unref because next is a newly created view and TransitionView
        //is now the sole owner of fNext
        this->attachChildToFront(fNext)->unref();

        fDone = false;
        //SkDebugf("--created transition\n");
    }

    ~TransitionView(){
        //SkDebugf("--deleted transition\n");
    }

    virtual void requestMenu(SkOSMenu* menu) {
        if (SampleView::IsSampleView(fNext))
            ((SampleView*)fNext)->requestMenu(menu);
    }

protected:
    virtual bool onQuery(SkEvent* evt) {
        if (SampleCode::TitleQ(*evt)) {
            SkString title;
            if (SampleCode::RequestTitle(fNext, &title)) {
                SampleCode::TitleR(evt, title.c_str());
                return true;
            }
            return false;
        }
        if (evt->isType(gIsTransitionQuery)) {
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }
    virtual bool onEvent(const SkEvent& evt) {
        if (evt.isType(gReplaceTransitionEvt)) {
            SkView* prev = fPrev;
            prev->ref();

            fPrev->detachFromParent();
            fPrev = (SkView*)SkEventSink::FindSink(evt.getFast32());
            (void)SampleView::SetUsePipe(fPrev, SkOSMenu::kOffState);
            //attach the new fPrev and call unref to balance the ref in onDraw
            this->attachChildToBack(fPrev)->unref();
            this->inval(NULL);

            SkASSERT(1 == prev->getRefCnt());
            prev->unref();
            return true;
        }
        if (evt.isType("transition-done")) {
            fNext->setLoc(0, 0);
            fNext->setClipToBounds(false);
            SkEvent* evt = new SkEvent(gReplaceTransitionEvt,
                                       this->getParent()->getSinkID());
            evt->setFast32(fNext->getSinkID());
            //increate ref count of fNext so it survives detachAllChildren
            fNext->ref();
            this->detachAllChildren();
            evt->post();
            return true;
        }
        return this->INHERITED::onEvent(evt);
    }
    virtual void onDrawBackground(SkCanvas* canvas) {}
    virtual void onDrawContent(SkCanvas* canvas) {
        if (fDone)
            return;

        if (is_overview(fNext) || is_overview(fPrev)) {
            fPipeState = SkOSMenu::kOffState;
        }

        SkScalar values[4];
        SkInterpolator::Result result = fInterp.timeToValues(SkTime::GetMSecs(), values);
        //SkDebugf("transition %x %d pipe:%d\n", this, result, fUsePipe);
        //SkDebugf("%f %f %f %f %d\n", values[0], values[1], values[2], values[3], result);
        if (SkInterpolator::kNormal_Result == result) {
            fPrev->setLocX(values[kPrevX]);
            fPrev->setLocY(values[kPrevY]);
            fNext->setLocX(values[kNextX]);
            fNext->setLocY(values[kNextY]);
            this->inval(NULL);
        }
        else {
            (new SkEvent("transition-done", this->getSinkID()))->post();
            fDone = true;
        }
    }

    virtual void onSizeChange() {
        this->INHERITED::onSizeChange();

        fNext->setSize(this->width(), this->height());
        fPrev->setSize(this->width(), this->height());

        SkScalar lr = 0, ud = 0;
        if (fAnimationDirection & (kLeftDirection|kULDirection|kDLDirection))
            lr = this->width();
        if (fAnimationDirection & (kRightDirection|kURDirection|kDRDirection))
            lr = -this->width();
        if (fAnimationDirection & (kUpDirection|kULDirection|kURDirection))
            ud = this->height();
        if (fAnimationDirection & (kDownDirection|kDLDirection|kDRDirection))
            ud = -this->height();

        fBegin[kPrevX] = fBegin[kPrevY] = 0;
        fBegin[kNextX] = lr;
        fBegin[kNextY] = ud;
        fNext->setLocX(lr);
        fNext->setLocY(ud);

        if (is_transition(fPrev))
            lr = ud = 0;
        fEnd[kPrevX] = -lr;
        fEnd[kPrevY] = -ud;
        fEnd[kNextX] = fEnd[kNextY] = 0;
        SkScalar blend[] = { 0.8f, 0.0f,
                             0.0f, SK_Scalar1 };
        fInterp.setKeyFrame(0, SkTime::GetMSecs(), fBegin, blend);
        fInterp.setKeyFrame(1, SkTime::GetMSecs()+kDurationMS, fEnd, blend);
    }

private:
    enum {
        kPrevX = 0,
        kPrevY = 1,
        kNextX = 2,
        kNextY = 3
    };
    SkView* fPrev;
    SkView* fNext;
    bool    fDone;
    SkInterpolator fInterp;

    enum Direction{
        kUpDirection    = 1,
        kURDirection    = 1 << 1,
        kRightDirection = 1 << 2,
        kDRDirection    = 1 << 3,
        kDownDirection  = 1 << 4,
        kDLDirection    = 1 << 5,
        kLeftDirection  = 1 << 6,
        kULDirection    = 1 << 7
    };

    Direction fAnimationDirection;
    SkScalar fBegin[4];
    SkScalar fEnd[4];

    typedef SampleView INHERITED;
};

SkView* create_transition(SkView* prev, SkView* next, int direction) {
#ifdef SK_BUILD_FOR_ANDROID
    // Disable transitions for Android
    return next;
#else
    return SkNEW_ARGS(TransitionView, (prev, next, direction));
#endif
}
