#include <tc.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <math.h>
#include <string.h>

/* Using builtin GCC Complex numbers */
#include <gr_fractal_complex.h>

#include "gr_fractal.h"

double min = -2., max = 2.;
unsigned steps = 100;
unsigned iter = 100;

tfun void wait_gtk (tout int *_res) {
  gtk_wait();
  *_res = 1;
}

void tfun init_table(tout int *_res) {
  gtk_init_table();
  *_res = 1;
}

void tfun draw_part(int _i, int _j, struct part _part, tout int *_res) {
dmesg("draw_part (%d,%d)\n", _i, _j);
  gtk_draw_part(_i, _j, &_part);
  *_res = 1;
}

tfun void calc_part(int _i, int _j, Complex _param, tout int *_res) {
  Complex z0 = CC(-RADIUS+_i*PART_STEP,-RADIUS+_j*PART_STEP);
  struct part *p = (struct part *)talloc(sizeof(*p));
  tval int res;
  int i, j;
  for (i = 0; i < PART_SIZE; i++) {
    for (j = 0; j < PART_SIZE; j++) {
      Complex z = z0 + CC(i*STEP,0) + CC(0,j*STEP);
      p->iter[i][j] = 0;
      do {
	if (p->iter[i][j]++ > MAX_ITERATION)
	  break;
	z = f(z,_param);
      } while(RE(z)*RE(z) + IM(z)*IM(z) < RADIUS*RADIUS);
    }
  }
dmesg("computed (%d,%d)\n", _i, _j);
  TCALL((draw_part(_i,_j,*p,&res)),(0));
  (int)res;
  tfree(p);
  *_res = 1;
}

struct xxx {
  tval int res;
};

tfun void draw_it(Complex param, tout int *_res) {
  int sum = 0;
  int i, j;
  struct xxx res[PARTS_IN_SIDE][PARTS_IN_SIDE];
  for (i = 0; i < PARTS_IN_SIDE; i++)
    for (j = 0; j < PARTS_IN_SIDE; j++)
      calc_part(i,j,param,&res[i][j].res);
  for (i = 0; i < PARTS_IN_SIDE; i++)
    for (j = 0; j < PARTS_IN_SIDE; j++)
      sum += res[i][j].res;
//  vmesg("%d parts computed succesfully\n", sum);
  *_res = sum;
}


int tmain(int argc, char *argv[]) {
  int i;
  tval int res0, res;
  Complex param;

  int shift = 0;
  for (i = 1; i < argc; i++) {
    if (shift > 0) argv[i] = argv[i + shift];
    if (strcmp(argv[i], "-min") == 0) {
      shift++; argc--;
      argv[i] = argv[i + shift];
      min = atof(argv[i]);
    } else if (strcmp(argv[i], "-max") == 0) {
      shift++; argc--;
      argv[i] = argv[i + shift];
      max = atof(argv[i]);
    } else if (strcmp(argv[i], "-steps") == 0) {
      shift++; argc--;
      argv[i] = argv[i + shift];
      steps = atol(argv[i]);
    } else if (strcmp(argv[i], "-iter") == 0) {
      shift++; argc--;
      argv[i] = argv[i + shift];
      iter = atol(argv[i]);
    } else {
      tprint("Unknown option\n");
      return -1;
    }
    shift++; i--; argc--;
  }


//  vmesg("%s: computing %d points in %d parts\n",
//	argv[0], TOTAL_POINTS, TOTAL_PARTS);
  
  TCALL((init_table(&res0)),(0));
  (int)res0; // wait for init completion

  for (i = 0; i < iter; i++) {
    tval int res;
    param = CC(min + (max - min)*i/steps,0);
    draw_it(param,&res);
    (int)res;
  }

  TCALL((wait_gtk(&res)), (0));
  (int)res;
  
  return 0;
}