// Published by devloop.org under MIT License, see: https://www.devloop.org/MIT-license.txt

#include <algorithm>
#include <SDL/SDL.h>
#include <emscripten.h>

namespace fire {
  constexpr int screen_width_{ 1024 };
  constexpr int screen_height_{ 512 };
  constexpr int fire_width_{ 256 };
  constexpr int fire_height_{ 128 };

  Uint8 pixels_[fire_width_ * fire_height_]{};
  SDL_Surface* fire_surface_{ nullptr };

  void Init(SDL_Surface* screen) {
    memset(pixels_ + (fire_width_ * (fire_height_-1)), 255, fire_width_);
    fire_surface_ = SDL_CreateRGBSurface(SDL_SWSURFACE, fire_width_, fire_height_, 
      screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, 0);
  }

  void SpreadFire(int src) {
			int rnd{ rand() % 6 };
      int dst{ src - rnd + 1 };
      if (dst >= fire_width_ && dst - fire_width_ < fire_width_ * fire_height_)
        pixels_[dst - fire_width_] = std::max(0, pixels_[src] - rnd);
  }

  void Step(void* arg) {
    if (SDL_MUSTLOCK(fire_surface_)) SDL_LockSurface(fire_surface_);
    for (int i{ 0 }; i < fire_width_ * fire_height_; ++i) {
      SpreadFire(i);
      Uint8 red{ static_cast<Uint8>(pixels_[i] == 0 ? 0 : 123 * (1 + sin(pixels_[i] / 255.0f))) };
      *((Uint32*)fire_surface_->pixels + i) = SDL_MapRGB(fire_surface_->format, red, pixels_[i], 0);
    }
		if (SDL_MUSTLOCK(fire_surface_)) SDL_UnlockSurface(fire_surface_);
    SDL_Surface* screen{ static_cast<SDL_Surface*>(arg) };
    SDL_Rect dst{ 0, 0, screen_width_, screen_height_ };
    SDL_BlitScaled(fire_surface_, nullptr, screen, &dst);
		SDL_Flip(screen);
  }
}

extern "C" int main(int argc, char** argv) {
  SDL_Init(SDL_INIT_VIDEO);
  SDL_Surface* screen{ SDL_SetVideoMode(fire::screen_width_, fire::screen_height_, 32, SDL_SWSURFACE) };
	fire::Init(screen);
  emscripten_set_main_loop_arg(fire::Step, screen, 0, 1);
  SDL_FreeSurface(fire::fire_surface_);
  SDL_Quit();
  return 0;
}
