/*
 * 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 "SampleCode.h"
#include "SkDumpCanvas.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkGradientShader.h"
#include "SkGraphics.h"
#include "SkImageDecoder.h"
#include "SkOSFile.h"
#include "SkPath.h"
#include "SkPicture.h"
#include "SkQuadTreePicture.h"
#include "SkRandom.h"
#include "SkRegion.h"
#include "SkShader.h"
#include "SkTileGridPicture.h"
#include "SkUtils.h"
#include "SkColorPriv.h"
#include "SkColorFilter.h"
#include "SkTime.h"
#include "SkTypeface.h"
#include "SkXfermode.h"

#include "SkStream.h"
#include "SkSurface.h"
#include "SkXMLParser.h"

class PictFileView : public SampleView {
public:
    PictFileView(const char name[] = NULL)
        : fFilename(name)
        , fBBox(kNo_BBoxType)
        , fTileSize(SkSize::Make(0, 0)) {
        for (int i = 0; i < kBBoxTypeCount; ++i) {
            fPictures[i] = NULL;
        }
    }

    virtual ~PictFileView() {
        for (int i = 0; i < kBBoxTypeCount; ++i) {
            SkSafeUnref(fPictures[i]);
        }
    }

    virtual void onTileSizeChanged(const SkSize &tileSize) SK_OVERRIDE {
        if (tileSize != fTileSize) {
            fTileSize = tileSize;
            SkSafeSetNull(fPictures[kTileGrid_BBoxType]);
        }
    }

protected:
    // overrides from SkEventSink
    virtual bool onQuery(SkEvent* evt) SK_OVERRIDE {
        if (SampleCode::TitleQ(*evt)) {
            SkString name("P:");
            const char* basename = strrchr(fFilename.c_str(), SkPATH_SEPARATOR);
            name.append(basename ? basename+1: fFilename.c_str());
            switch (fBBox) {
            case kNo_BBoxType:
                // No name appended
                break;
            case kRTree_BBoxType:
                name.append(" <bbox: R>");
                break;
            case kQuadTree_BBoxType:
                name.append(" <bbox: Q>");
                break;
            case kTileGrid_BBoxType:
                name.append(" <bbox: T>");
                break;
            default:
                SkASSERT(false);
                break;
            }
            SampleCode::TitleR(evt, name.c_str());
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }

    virtual bool onEvent(const SkEvent& evt) SK_OVERRIDE {
        if (evt.isType("PictFileView::toggleBBox")) {
            fBBox = (BBoxType)((fBBox + 1) % kBBoxTypeCount);
            return true;
        }
        return this->INHERITED::onEvent(evt);
    }

    virtual void onDrawContent(SkCanvas* canvas) SK_OVERRIDE {
        SkASSERT(static_cast<int>(fBBox) < kBBoxTypeCount);
        SkPicture** picture = fPictures + fBBox;

        if (!*picture) {
            *picture = LoadPicture(fFilename.c_str(), fBBox);
        }
        if (*picture) {
            canvas->drawPicture(**picture);
        }
    }

private:
    enum BBoxType {
        kNo_BBoxType,
        kQuadTree_BBoxType,
        kRTree_BBoxType,
        kTileGrid_BBoxType,

        kLast_BBoxType = kTileGrid_BBoxType
    };
    static const int kBBoxTypeCount = kLast_BBoxType + 1;

    SkString    fFilename;
    SkPicture*  fPictures[kBBoxTypeCount];
    BBoxType    fBBox;
    SkSize      fTileSize;

    SkPicture* LoadPicture(const char path[], BBoxType bbox) {
        SkAutoTUnref<SkPicture> pic;

        SkBitmap bm;
        if (SkImageDecoder::DecodeFile(path, &bm)) {
            bm.setImmutable();
            SkPictureRecorder recorder;
            SkCanvas* can = recorder.beginRecording(bm.width(), bm.height());
            can->drawBitmap(bm, 0, 0, NULL);
            pic.reset(recorder.endRecording());
        } else {
            SkFILEStream stream(path);
            if (stream.isValid()) {
                pic.reset(SkPicture::CreateFromStream(&stream));
            } else {
                SkDebugf("coun't load picture at \"path\"\n", path);
            }

            if (false) {
                SkSurface* surf = SkSurface::NewRasterPMColor(pic->width(), pic->height());
                surf->getCanvas()->drawPicture(*pic);
                surf->unref();
            }
            if (false) { // re-record
                SkPictureRecorder recorder;
                pic->draw(recorder.beginRecording(pic->width(), pic->height()));
                SkAutoTUnref<SkPicture> p2(recorder.endRecording());

                SkString path2(path);
                path2.append(".new.skp");
                SkFILEWStream writer(path2.c_str());
                p2->serialize(&writer);
            }
        }

        if (NULL == pic) {
            return NULL;
        }

        SkAutoTUnref<SkPictureFactory> factory;
        switch (bbox) {
        case kNo_BBoxType:
            // no bbox playback necessary
            return pic.detach();
        case kRTree_BBoxType:
            break;
        case kQuadTree_BBoxType:
            factory.reset(SkNEW(SkQuadTreePictureFactory));
            break;
        case kTileGrid_BBoxType: {
            SkASSERT(!fTileSize.isEmpty());
            SkTileGridPicture::TileGridInfo gridInfo;
            gridInfo.fMargin = SkISize::Make(0, 0);
            gridInfo.fOffset = SkIPoint::Make(0, 0);
            gridInfo.fTileInterval = fTileSize.toRound();
            factory.reset(SkNEW_ARGS(SkTileGridPictureFactory, (gridInfo)));
            break;
        }
        default:
            SkASSERT(false);
        }

        SkPictureRecorder recorder(factory);
        pic->draw(recorder.beginRecording(pic->width(), pic->height(),
                                          SkPicture::kOptimizeForClippedPlayback_RecordingFlag));
        return recorder.endRecording();
    }

    typedef SampleView INHERITED;
};

SampleView* CreateSamplePictFileView(const char filename[]);
SampleView* CreateSamplePictFileView(const char filename[]) {
    return new PictFileView(filename);
}

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

#if 0
static SkView* MyFactory() { return new PictFileView; }
static SkViewRegister reg(MyFactory);
#endif
