#include "SampleCode.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkBlurMaskFilter.h"
#include "SkPaint.h"
#include "SkPath.h"
#include "SkXfermode.h"
#include "SkMatrix.h"
#include "SkColor.h"
#include "SkRandom.h"
static void set2x3(SkMatrix* m, float a, float b, float c, float d, float e, float f) {
    m->reset();
    m->set(0, a);
    m->set(1, b);
    m->set(2, c);
    m->set(3, d);
    m->set(4, e);
    m->set(5, f);
}
static SkRandom gRand;
static bool return_large;
static bool return_undef;
static bool quick;
static bool scale_large;
static int scval = 1;
static float transval = 0;
static int R(float x) {
  return (int)floor(SkScalarToFloat(gRand.nextUScalar1()) * x);
}
#if defined _WIN32
#pragma warning ( push )
#pragma warning ( disable : 4756 )
#endif
static float huge() {
    double d = 1e100;
    float f = (float)d;
    return f;
}
#if defined _WIN32
#pragma warning ( pop )
#endif
static float make_number() {
  float v = 0;
  int sel;
  if (return_large == true && R(3) == 1) {
      sel = R(6);
  } else {
      sel = R(4);
  }
  if (return_undef == false && sel == 0) {
      sel = 1;
  }
  if (R(2) == 1) {
      v = (float)R(100);
  } else {
      switch (sel) {
        case 0: break;
        case 1: v = 0; break;
        case 2: v = 0.000001f; break;
        case 3: v = 10000; break;
        case 4: v = 2000000000; break;
        case 5: v = huge(); break;
      }
  }
  if (R(4) == 1) {
      v = -v;
  }
  return v;
}
static SkColor make_color() {
  if (R(2) == 1) return 0xFFC0F0A0; else return 0xFF000090;
}
static SkColor make_fill() {
#if 0#else
    return make_color();
#endif
}
static void do_fuzz(SkCanvas* canvas) {
    SkPath path;
    SkPaint paint;
    paint.setAntiAlias(true);
  for (int i=0;i<100;i++) {
  switch (R(33)) {
    case 0:
          paint.setColor(make_fill());
      break;
    case 1:
      paint.setAlpha(gRand.nextU() & 0xFF);
      break;
      case 2: {
          SkXfermode::Mode mode;
          switch (R(3)) {
            case 0: mode = SkXfermode::kSrc_Mode; break;
            case 1: mode = SkXfermode::kXor_Mode; break;
            case 2:
            default:                mode = SkXfermode::kSrcOver_Mode; break;
          }
          paint.setXfermodeMode(mode);
      }
      break;
    case 3:
      switch (R(2)) {
          case 0: paint.setStrokeCap(SkPaint::kRound_Cap); break;
        case 1: paint.setStrokeCap(SkPaint::kButt_Cap); break;
      }
      break;
    case 4:
      switch (R(2)) {
          case 0: paint.setStrokeJoin(SkPaint::kRound_Join); break;
        case 1: paint.setStrokeJoin(SkPaint::kMiter_Join); break;
      }
      break;
    case 5:
      paint.setStrokeWidth(make_number());
      break;
    case 6:
      paint.setStrokeMiter(make_number());
      break;
    case 7:
      if (quick == true) break;
          SkSafeUnref(paint.setMaskFilter(SkBlurMaskFilter::Create(kNormal_SkBlurStyle,
                                                                   make_number())));
      break;
    case 8:
      if (quick == true) break;
            break;
    case 9:
      if (quick == true) break;
                  break;
    case 10:
      canvas->restore();
      break;
    case 11:
      canvas->rotate(make_number());
      break;
    case 12:
      canvas->save();
      break;
    case 13:
      canvas->scale(-1,-1);
      break;
    case 14:
      if (quick == true) break;
      if (transval == 0) {
        transval = make_number();
        canvas->translate(transval,0);
      } else {
        canvas->translate(-transval,0);
        transval = 0;
      }
      break;
          case 15: {
              SkRect r;
              r.set(make_number(),make_number(),make_number(),make_number());
              SkPaint::Style s = paint.getStyle();
              paint.setStyle(SkPaint::kFill_Style);
              canvas->drawRect(r, paint);
              paint.setStyle(s);
                        } break;
    case 16:
      if (quick == true) break;
      break;
          case 17: {
          SkRect r;
          r.set(make_number(),make_number(),make_number(),make_number());
              SkPaint::Style s = paint.getStyle();
              paint.setStyle(SkPaint::kFill_Style);
          canvas->drawRect(r, paint);
              paint.setStyle(s);
          } break;
    case 18:
          path.reset();
      break;
    case 19:
            break;
    case 20:
          path.close();
      break;
          case 21: {
          SkPaint::Style s = paint.getStyle();
          paint.setStyle(SkPaint::kFill_Style);
          canvas->drawPath(path, paint);
          paint.setStyle(s);
          } break;
          case 22: {
              SkPaint::Style s = paint.getStyle();
              paint.setStyle(SkPaint::kFill_Style);
              canvas->drawPath(path, paint);
              paint.setStyle(s);
          } break;
          case 23: {
              SkRect r;
              r.set(make_number(),make_number(),make_number(),make_number());
              SkPaint::Style s = paint.getStyle();
              paint.setStyle(SkPaint::kStroke_Style);
              canvas->drawRect(r, paint);
              paint.setStyle(s);
          } break;
    case 24:
      if (quick == true) break;
            break;
    case 25:
      if (quick == true) break;
            break;
    case 26:
      if (quick == true) break;
            break;
    case 27:
      path.lineTo(make_number(),make_number());
      break;
    case 28:
      path.moveTo(make_number(),make_number());
      break;
    case 29:
      if (quick == true) break;
      path.quadTo(make_number(),make_number(),make_number(),make_number());
      break;
          case 30: {
      if (quick == true) break;
              SkMatrix matrix;
      set2x3(&matrix, make_number(),make_number(),make_number(),make_number(),make_number(),make_number());
              canvas->concat(matrix);
          } break;
          case 31: {
      if (quick == true) break;
          SkMatrix matrix;
          set2x3(&matrix, make_number(),make_number(),make_number(),make_number(),make_number(),make_number());
          canvas->setMatrix(matrix);
          } break;
    case 32:
      if (scale_large == true) {
        switch (scval) {
          case 0: canvas->scale(-1000000000,1);
                  canvas->scale(-1000000000,1);
                  scval = 1; break;
          case 1: canvas->scale(-.000000001f,1); scval = 2; break;
          case 2: canvas->scale(-.000000001f,1); scval = 0; break;
        }
      }
      break;
  }
  }
}
class FuzzView : public SampleView {
public:
    FuzzView() {
        this->setBGColor(0xFFDDDDDD);
    }
protected:
        virtual bool onQuery(SkEvent* evt) {
        if (SampleCode::TitleQ(*evt)) {
            SampleCode::TitleR(evt, "Fuzzer");
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }
    void drawBG(SkCanvas* canvas) {
        canvas->drawColor(0xFFDDDDDD);
    }
    virtual void onDrawContent(SkCanvas* canvas) {
        do_fuzz(canvas);
        this->inval(NULL);
    }
private:
    typedef SkView INHERITED;
};
static SkView* MyFactory() { return new FuzzView; }
static SkViewRegister reg(MyFactory);