#include "segmentation.h"

/*find if a line contain black pixel*/
/*If contain a black pixel return 0*/
/*x is the height*/
int FindBlackPixel(SDL_Surface *img, int x)
{
    Uint32 pixel;
    int w = img->w;
    Uint8 r, g, b;
    /*A boolean that memorize if the line contain black pixel ornot*/
    int bool = 1;

    for (int i = 0; i < w; i++)
    {
        pixel = getpixel(img, i, x);
        SDL_GetRGB(pixel, img->format, &r, &g, &b);

        if (r == 0)
        {
            bool = 0;
            break;
        }
    }

    return bool;
}

/*Main function which print line on image*/

void CutLines(SDL_Surface *img, int d)
{
    Uint32 pixel;
    Uint8 r, g, b;
    int end_line = 0;
    int begin_line = 0;
    int w = img->w;
    int h = img->h;
    d = d % 2;

    for (int i = 0; i < h; i++)
    {
        for (int j = 0; j < w; j++)
        {
            pixel = getpixel(img, j, i);
            SDL_GetRGB(pixel, img->format, &r, &g, &b);

            if (r == 0) /*after binerize is not necessary to test the others
                           values*/
            {
                if (FindBlackPixel(img, i - 1))
                {
                    DrawALine(img, i - 1);
                    begin_line = i - 1;
                }

                if (FindBlackPixel(img, i + 1)) /*same but for the under line*/
                {
                    DrawALine(img, i + 1);
                    end_line = i + 1;
                }

                if (end_line && begin_line)
                {
                    if (d)
                    {
                        CutColumn(img, begin_line, end_line);
                    }
                    end_line = 0;
                    begin_line = 0;
                }
                break;
            }
        }
    }
}

/*draw a line if necessary*/
void DrawALine(SDL_Surface *img, int x)
{
    Uint32 pixel;
    int w = img->w;

    for (int i = 0; i < w; i++)
    {
        pixel = SDL_MapRGB(img->format, 255, 150, 255);
        putpixel(img, i, x, pixel);
    }
}

/*Main function for mark the column on the image*/
void CutColumn(SDL_Surface *img, int begin_line, int end_line)
{
    Uint8 r, g, b;
    Uint32 pixel;
    int w = img->w;

    for (int i = 0; i < w; i++)
    {
        for (int j = begin_line; j < end_line; j++)
        {
            pixel = getpixel(img, i, j);
            SDL_GetRGB(pixel, img->format, &r, &g, &b);

            if (r == 0) /*after binerize is not necessary to test the others
                           values */
            {
                if (FindBlackPixelInColumn(
                        img, begin_line, end_line,
                        i - 1)) /*For the first black pixel we meet, we check if
                                   the upper line is full of white and then we
                                   draw a line for mark the begin of a new
                                   line*/
                {
                    DrawAColumn(img, i - 1, begin_line, end_line);
                }

                if (FindBlackPixelInColumn(
                        img, begin_line, end_line,
                        i + 1)) /*same but for the under line*/
                {
                    DrawAColumn(img, i + 1, begin_line, end_line);
                }
                break;
            }
        }
    }
}

/*find if a column contain black pixel*/
/*If contain a black pixel return 0*/
/*start is the value on weight*/
/*begin_line and end_line the value on height*/
int FindBlackPixelInColumn(SDL_Surface *img, int begin_line, int end_line,
                           int start)
{
    Uint32 pixel;
    Uint8 r, g, b;
    int bool =
        1; /*A boolean that memorize if the line contain black pixel or not*/

    for (int i = begin_line; i < end_line; i++)
    {
        pixel = getpixel(img, start, i);
        SDL_GetRGB(pixel, img->format, &r, &g, &b);

        if (r == 0)
        {
            bool = 0;
            break;
        }
    }

    return bool;
}

/*Draw a column between two lines and characters*/
void DrawAColumn(SDL_Surface *img, int y, int x, int end_line)
{
    Uint32 pixel;

    for (int i = x; i < end_line; i++)
    {
        pixel = SDL_MapRGB(img->format, 1, 100, 100);
        putpixel(img, y, i, pixel);
    }
}

int pixelSpacingHorizontal(SDL_Surface *img)
{
    Uint32 pixel;
    Uint8 r;
    Uint8 g;
    Uint8 b;
    int white = 0;
    int black = 0;

    for (int i = 0; i < img->h; i++)
    {
        for (int j = 0; j < img->w; j++)
        {
            pixel = getpixel(img, j, i);
            SDL_GetRGB(pixel, img->format, &r, &g, &b);
            if (r == 255 && g == 255 && b == 255)
            {
                white++;
            }
            else
            {
                black++;
            }
        }
    }
    return (white) / (black / 2);
}

// fonctionne pareil que la version horizontale
int pixelSpacingVertical(SDL_Surface *img)
{
    Uint32 pixel;
    Uint8 r;
    Uint8 g;
    Uint8 b;
    int white = 0;
    int black = 0;

    for (int i = 0; i < img->w; i++)
    {
        for (int j = 0; j < img->h; j++)
        {
            pixel = getpixel(img, i, j);
            SDL_GetRGB(pixel, img->format, &r, &g,
                       &b); // recup les r g b du pixel (i, j) car vertical
            if (r == 255 && g == 255
                && b == 255) // pareil qu'en version horizontal
            {
                white++;
            }
            else
            {
                black++;
            }
        }
    }
    return (white) / (black);
}

void blockDetection_horizontal(SDL_Surface *img)
{
    Uint32 pixel;
    Uint8 r, g, b;
    int hori = pixelSpacingHorizontal(img) * 30;
    int countWhite;

    for (int i = 0; i < img->h; i++)
    {
        countWhite = 0;
        for (int j = 0; j < img->w; j++)
        {
            pixel = getpixel(img, j, i);
            SDL_GetRGB(pixel, img->format, &r, &g, &b);
            if (r == 255 && g == 255 && b == 255)
            {
                countWhite++;
            }
            if (r == 0 && g == 0 && b == 0)
            {
                if (countWhite <= hori)
                {
                    int k = j - 1;
                    while (countWhite > 0)
                    {
                        pixel = SDL_MapRGB(img->format, 0, 0, 0);
                        putpixel(img, k, i, pixel);
                        countWhite--;
                        k--;
                    }
                }
                else
                {
                    countWhite = 0;
                }
            }
        }
    }
}

// remplis les espaces verticaux entre deux pixels.
// Fonctionne pareil que la version horizontale
void blockDetection_vertical(SDL_Surface *img)
{
    Uint32 pixel;
    Uint8 r;
    Uint8 g;
    Uint8 b;
    int verti = pixelSpacingVertical(img) * 3;
    int countBlack;

    for (int i = 0; i < img->w; i++)
    {
        countBlack = 0;
        for (int j = 0; j < img->h; j++)
        {
            pixel = getpixel(img, i, j);
            SDL_GetRGB(pixel, img->format, &r, &g, &b);
            if (r == 255 && g == 255 && b == 255)
            {
                countBlack++;
            }
            else
            {
                if (countBlack <= verti)
                {
                    int k = j - 1;
                    while (countBlack > 0)
                    {
                        pixel = SDL_MapRGB(img->format, 0, 0, 0);
                        putpixel(img, i, k, pixel);
                        countBlack--;
                        k--;
                    }
                }
                else
                {
                    countBlack = 0;
                }
            }
        }
    }
}

// dessine les blocs en les noircissant entierement
//(fait un ET logique du RLSA horizontal et RLSA vertical)
// img c'est l'image qui va contenir des blocs remplis de noir
// imgHor a subi bloc detection horizontal
// imgver a subi bloc detection vertical
void drawBlocksMulti(SDL_Surface *img, SDL_Surface *imgHor, SDL_Surface *imgVer)
{
    Uint32 pixelHor;
    Uint32 pixelVer;
    Uint32 pixel;
    Uint8 r;
    Uint8 g;
    Uint8 b;

    for (int i = 1; i + 1 < img->w; i++)
    {
        for (int j = 1; j + 1 < img->h; j++)
        {
            pixelHor = getpixel(imgHor, i, j);
            SDL_GetRGB(pixelHor, imgHor->format, &r, &g, &b);
            if (r == 0 && g == 0 && b == 0)
            {
                pixelVer = getpixel(imgVer, i, j);
                SDL_GetRGB(pixelVer, imgVer->format, &r, &g, &b);
                if (r == 0 && g == 0 && b == 0)
                {
                    pixel = SDL_MapRGB(img->format, 0, 0, 0);
                    putpixel(img, i, j, pixel);
                }
            }
        }
    }
}

void drawBlocks(SDL_Surface *img, SDL_Surface *imgHor)
{
    Uint32 pixelHor;
    Uint32 pixelLine;
    Uint8 r;
    Uint8 g;
    Uint8 b;
    int w;
    for (int i = 1; i + 1 < img->w; i++)
    {
        for (int j = 1; j + 1 < img->h; j++)
        {
            pixelHor = getpixel(imgHor, i, j);
            SDL_GetRGB(pixelHor, imgHor->format, &r, &g, &b);
            if (r == 0 && g == 0 && b == 0)
            {
                w = img->w;
                for (int k = 0; k < w; k++)
                {
                    pixelLine = SDL_MapRGB(img->format, 0, 0, 0);
                    putpixel(img, k, j, pixelLine);
                }
            }
        }
    }
}

void drawBlocksLines(SDL_Surface *img, SDL_Surface *imgRLSA)
{
    Uint32 pixel;
    Uint32 pixelRLSA;
    Uint32 pixelUp;
    Uint32 pixelDown;
    Uint32 pixelLeft;
    Uint32 pixelRight;
    Uint8 r;
    Uint8 g;
    Uint8 b;

    for (int i = 1; i + 1 < img->w; i++)
    {
        for (int j = 1; j + 1 < img->h; j++)
        {
            pixelRLSA = getpixel(imgRLSA, i, j);
            SDL_GetRGB(pixelRLSA, imgRLSA->format, &r, &g, &b);
            if (r == 0 && g == 0 && b == 0) // si le pixel est noir,
            {
                pixelUp = getpixel(imgRLSA, i, j - 1);
                SDL_GetRGB(pixelUp, imgRLSA->format, &r, &g, &b);
                if (r == 255 && g == 255 && b == 255) // pixel du haut
                {
                    pixel = SDL_MapRGB(img->format, 0, 0, 255);
                    putpixel(img, i, j - 1, pixel);
                }
                else
                {
                    pixelDown = getpixel(imgRLSA, i, j + 1);
                    SDL_GetRGB(pixelDown, imgRLSA->format, &r, &g, &b);
                    if (r == 255 && g == 255 && b == 255) // pixel d'en bas
                    {
                        pixel = SDL_MapRGB(img->format, 0, 0, 255);
                        putpixel(img, i, j + 1, pixel);
                    }
                    else
                    {
                        pixelLeft = getpixel(imgRLSA, i - 1, j);
                        SDL_GetRGB(pixelLeft, imgRLSA->format, &r, &g, &b);
                        if (r == 255 && g == 255 && b == 255) // pixel de gauche
                        {
                            pixel = SDL_MapRGB(img->format, 0, 0, 255);
                            putpixel(img, i, j - 1, pixel);
                        }
                        else
                        {
                            pixelRight = getpixel(imgRLSA, i + 1, j);
                            SDL_GetRGB(pixelRight, imgRLSA->format, &r, &g, &b);
                            if (r == 255 && g == 255
                                && b == 255) // pixel de droite
                            {
                                pixel = SDL_MapRGB(img->format, 0, 0, 255);
                                putpixel(img, i, j + 1, pixel);
                            }
                        }
                    }
                }
            }
        }
    }
}

/*make an histogramme of the black pixel in column of the image*/
/*histo1 is a pointer on a int array*/
void histo(SDL_Surface *img, int *histo1)
{
    Uint32 pixel;
    Uint8 r, g, b;
    int w = img->w;
    int h = img->h;

    for (int r = 0; r < w; r++)
    {
        histo1[r] = 0;
    }

    for (int i = 0; i < w; i++)
    {
        int s = 0;
        for (int j = 0; j < h; j++)
        {
            pixel = getpixel(img, i, j);
            SDL_GetRGB(pixel, img->format, &r, &g, &b);

            if (r == 255)
            {
                s++;
            }
        }
        histo1[i] = h - s;
    }
}
/*useless actually*/
/*void cutchar(SDL_Surface *img){
  int w;
  w = img -> w;
  int *histog = malloc(w * sizeof(int));
  int average = average1(img);
  printf("%i\n",average);
  int s = 0;
  int bool1=0;
  histo(img, histog);
  for (int i = 0; i < img -> w; i++){
    if (s > average){
      printf("histo(%i) = %i",i,histog[i]);
      DrawAColumn(img, i-s/2, 0,img->h -1);
    }
    if (histog[i] != 0){
        if(bool1)
        {
          bool1 =0;
        }
      s++;
    }
    else
    {
      bool1=1;
      s =0;
    }
  }
  free(histog);
}*/

/*make the average of all suite of zero in the histogramme*/
int average(SDL_Surface *img)
{
    int w = img->w;
    int *histog = malloc(w * sizeof(int));
    histo(img, histog);
    int s = 0;
    int sum = 0;
    int r = 0;
    int bool1 = 1;

    for (int i = 0; i < img->w; i++)
    {
        if (histog[i] == 0)
        {
            if (bool1)
            {
                bool1 = 0;
                r += 1;
            }
            s++;
        }
        else
        {
            sum += s;
            bool1 = 1;
            s = 0;
        }
    }

    free(histog);
    return sum / r;
}

/*cut all of the word of a line*/
void cutword(SDL_Surface *img)
{
    int w = img->w;
    int *histog = malloc(w * sizeof(int));
    histo(img, histog);
    int bool1 = 1;
    int r = average(img);
    int s = 0;
    int pos = 0;
    int i;

    for (i = 0; i < img->w; i++)
    {
        if (histog[i] == 0)
        {
            if (bool1)
            {
                pos = i;
                bool1 = 0;
            }
            s++;
        }
        else
        {
            if (s >= r * 1.4)
            {
                DrawAColumn(img, pos, 0, img->h);
            }
            bool1 = 1;
            s = 0;
        }
    }

    if (i == img->w)
    {
        DrawAColumn(img, pos, 0, img->h);
    }

    free(histog);
}
