// Copyright 2020 Google LLC.
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
#include "tools/fiddle/examples.h"
REG_FIDDLE_ANIMATED(l_system_plant, 256, 256, false, 0, 3) {
// L-System
// https://en.wikipedia.org/wiki/L-system#Example_7:_Fractal_plant

struct rules_t {
    char c;
    std::string s;
};

rules_t rules[6] = {
    {'X', "F-[[X]+X]+F[+FX]-X"},
    {'F', "FF"},
    {'+', "+"},
    {'-', "-"},
    {'[', "["},
    {']', "]"},
};

std::string E(std::string s) {
    if (s.size() == 0) {
        return "";
    }
    for (int i=0; i<6; i++) {
        if (rules[i].c == s[0]) {
            return rules[i].s + E(s.substr(1));
        }
    }
    return "";
}

struct Pt {
  SkScalar x;
  SkScalar y;
  SkScalar a;
};

void draw(SkCanvas* canvas) {
  canvas->drawColor(SK_ColorLTGRAY);

  SkPaint p;
  p.setColor(0xFFA6761D);
  p.setAntiAlias(true);
  p.setStyle(SkPaint::kStroke_Style);
  p.setStrokeWidth(1);

  std::vector<struct Pt> ptstack;
  std::string plant = E(E(E(E(E("X")))));
  const double len = 2.5;
  struct Pt pt = {128, 256, 3.14};
  SkPathBuilder path;
  path.moveTo(pt.x, pt.y);

  for (std::string::iterator it=plant.begin(); it!=plant.end(); ++it) {
    if (*it == 'F') {
      pt.x += len*sin(pt.a);
      pt.y += len*cos(pt.a);
      path.lineTo(pt.x, pt.y);
    } else if (*it == '+') {
      pt.a += (0.15 + sin(frame*2.0*3.14159)*0.05);
    } else if (*it == '-') {
      pt.a += (-0.15 + sin(frame*2.0*3.14159)*0.05);
    } else if (*it == '[') {
      ptstack.push_back(pt);
    } else if (*it == ']') {
      pt = ptstack.back();
      ptstack.pop_back();
      path.moveTo(pt.x, pt.y);
    }
  }
  canvas->drawPath(path.detach(), p);
}
}  // END FIDDLE
