/* Goom Project
 * Copyright (C) <2003> iOS-Software
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "lines.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include "goom_tools.h"
#include "drawmethods.h"
#include "goom_plugin_info.h"

static inline unsigned char
lighten (unsigned char value, float power)
{
  int val = value;
  float t = (float) val * log10 (power) / 2.0;

  if (t > 0) {
    val = (int) t;              /* (32.0f * log (t)); */
    if (val > 255)
      val = 255;
    if (val < 0)
      val = 0;
    return val;
  } else {
    return 0;
  }
}

static void
lightencolor (guint32 * col, float power)
{
  unsigned char *color;

  color = (unsigned char *) col;
  *color = lighten (*color, power);
  color++;
  *color = lighten (*color, power);
  color++;
  *color = lighten (*color, power);
  color++;
  *color = lighten (*color, power);
}



static void
genline (int id, float param, GMUnitPointer * l, int rx, int ry)
{
  int i;

  switch (id) {
    case GML_HLINE:
      for (i = 0; i < 512; i++) {
        l[i].x = ((float) i * rx) / 512.0f;
        l[i].y = param;
        l[i].angle = G_PI / 2.0f;
      }
      return;
    case GML_VLINE:
      for (i = 0; i < 512; i++) {
        l[i].y = ((float) i * ry) / 512.0f;
        l[i].x = param;
        l[i].angle = 0.0f;
      }
      return;
    case GML_CIRCLE:
      for (i = 0; i < 512; i++) {
        float cosa, sina;

        l[i].angle = 2.0f * G_PI * (float) i / 512.0f;
        cosa = param * cos (l[i].angle);
        sina = param * sin (l[i].angle);
        l[i].x = ((float) rx / 2.0f) + cosa;
        l[i].y = (float) ry / 2.0f + sina;
      }
      return;
  }
}

static guint32
getcouleur (int mode)
{
  switch (mode) {
    case GML_RED:
      return (230 << (ROUGE * 8)) | (120 << (VERT * 8)) | (18 << (BLEU * 8));
    case GML_ORANGE_J:
      return (120 << (VERT * 8)) | (252 << (ROUGE * 8)) | (18 << (BLEU * 8));
    case GML_ORANGE_V:
      return (160 << (VERT * 8)) | (236 << (ROUGE * 8)) | (40 << (BLEU * 8));
    case GML_BLEUBLANC:
      return (40 << (BLEU * 8)) | (220 << (ROUGE * 8)) | (140 << (VERT * 8));
    case GML_VERT:
      return (200 << (VERT * 8)) | (80 << (ROUGE * 8)) | (18 << (BLEU * 8));
    case GML_BLEU:
      return (250 << (BLEU * 8)) | (30 << (VERT * 8)) | (80 << (ROUGE * 8));
    case GML_BLACK:
      return (16 << (BLEU * 8)) | (16 << (VERT * 8)) | (16 << (ROUGE * 8));
  }
  return 0;
}

void
goom_lines_set_res (GMLine * gml, int rx, int ry)
{
  if (gml != NULL) {
    gml->screenX = rx;
    gml->screenY = ry;

    genline (gml->IDdest, gml->param, gml->points2, rx, ry);
  }
}


static void
goom_lines_move (GMLine * l)
{
  int i;
  unsigned char *c1, *c2;

  for (i = 0; i < 512; i++) {
    l->points[i].x = (l->points2[i].x + 39.0f * l->points[i].x) / 40.0f;
    l->points[i].y = (l->points2[i].y + 39.0f * l->points[i].y) / 40.0f;
    l->points[i].angle =
        (l->points2[i].angle + 39.0f * l->points[i].angle) / 40.0f;
  }

  c1 = (unsigned char *) &l->color;
  c2 = (unsigned char *) &l->color2;
  for (i = 0; i < 4; i++) {
    int cc1, cc2;

    cc1 = *c1;
    cc2 = *c2;
    *c1 = (unsigned char) ((cc1 * 63 + cc2) >> 6);
    ++c1;
    ++c2;
  }

  l->power += l->powinc;
  if (l->power < 1.1f) {
    l->power = 1.1f;
    l->powinc = (float) (goom_irand (l->goomInfo->gRandom, 20) + 10) / 300.0f;
  }
  if (l->power > 17.5f) {
    l->power = 17.5f;
    l->powinc = -(float) (goom_irand (l->goomInfo->gRandom, 20) + 10) / 300.0f;
  }

  l->amplitude = (99.0f * l->amplitude + l->amplitudeF) / 100.0f;
}

void
goom_lines_switch_to (GMLine * gml, int IDdest,
    float param, float amplitude, int col)
{
  genline (IDdest, param, gml->points2, gml->screenX, gml->screenY);
  gml->IDdest = IDdest;
  gml->param = param;
  gml->amplitudeF = amplitude;
  gml->color2 = getcouleur (col);
}

GMLine *
goom_lines_init (PluginInfo * goomInfo, int rx, int ry,
    int IDsrc, float paramS, int coulS, int IDdest, float paramD, int coulD)
{
  GMLine *l = (GMLine *) malloc (sizeof (GMLine));

  l->goomInfo = goomInfo;

  l->points = (GMUnitPointer *) malloc (512 * sizeof (GMUnitPointer));
  l->points2 = (GMUnitPointer *) malloc (512 * sizeof (GMUnitPointer));
  l->nbPoints = 512;

  l->IDdest = IDdest;
  l->param = paramD;

  l->amplitude = l->amplitudeF = 1.0f;

  genline (IDsrc, paramS, l->points, rx, ry);
  genline (IDdest, paramD, l->points2, rx, ry);

  l->color = getcouleur (coulS);
  l->color2 = getcouleur (coulD);

  l->screenX = rx;
  l->screenY = ry;

  l->power = 0.0f;
  l->powinc = 0.01f;

  goom_lines_switch_to (l, IDdest, paramD, 1.0f, coulD);

  return l;
}

void
goom_lines_free (GMLine ** l)
{
  free ((*l)->points2);
  free ((*l)->points);
  free (*l);
  l = NULL;
}

void
goom_lines_draw (PluginInfo * plug, GMLine * line, gint16 data[512], Pixel * p)
{
  if (line != NULL) {
    int i, x1, y1;
    guint32 color = line->color;
    GMUnitPointer *pt = &(line->points[0]);

    float cosa = cos (pt->angle) / 1000.0f;
    float sina = sin (pt->angle) / 1000.0f;

    lightencolor (&color, line->power);

    x1 = (int) (pt->x + cosa * line->amplitude * data[0]);
    y1 = (int) (pt->y + sina * line->amplitude * data[0]);

    for (i = 1; i < 512; i++) {
      int x2, y2;
      GMUnitPointer *pt = &(line->points[i]);

      float cosa = cos (pt->angle) / 1000.0f;
      float sina = sin (pt->angle) / 1000.0f;

      x2 = (int) (pt->x + cosa * line->amplitude * data[i]);
      y2 = (int) (pt->y + sina * line->amplitude * data[i]);

      plug->methods.draw_line (p, x1, y1, x2, y2, color, line->screenX,
          line->screenY);

      x1 = x2;
      y1 = y2;
    }
    goom_lines_move (line);
  }
}
