/* Standard includes */

#include <stdio.h>

/* psLib includes */

#include "psMemory.h"

/* streakremove includes */

#include "streaksextern.h"
#include "Line.h"

/** Create a list of pixel positions from a Streaks pointer list
    converting the equatorial coordinates into the pixel coordinates
    using strkAstrom and building streak pixels using the specified
    width and store in StreakPixels object returned

    @param[in] streaks List of streak pointer objects to convert to
                       pixel positions output in StreakPixels
    @param[in] astrom Astrometry object for converting streak equatorial
                      coordinates into pixel positions
    @param[in] numCols number of columns in the image to map streak equatorial
                       coordinates into pixel positions
    @param[in] numRows number of rows in the image to map streak equatorial
                       coordinates into pixel positions
    @return list of PixelPos pointers for the streaks mapped to the image
            pixels
*/
    
StreakPixels *streak_on_component(Streaks *streaks, strkAstrom *astrom,
                                  int numCols, int numRows)
{
    int i;
    Line line;
    StreakPixels *pixels = psImageAlloc(numCols, numRows, PS_TYPE_U8);
    psImageInit(pixels, 0);
    int streaksOnComponent = 0;

    int minX, minY, maxX, maxY;

    // find the chip dimensions in the tangent-plane coordinates (length of hypotenuse)
    componentBounds (&minX, &minY, &maxX, &maxY, astrom, numCols, numRows);

    for (i = 0; i != streaks->size; ++i)
    {
        /* Convert streak equatorial coordinates into pixel based line */

        line.width = streaks->list[i].width;

	/* Use tangent plane coordinates to narrow down the ra,dec range of the line closer to
	 * the chip boundaries.  Use these new ra,dec positions to generate the line on the
	 * chip using the full non-linear astrometry */
	   
	// project the ends of the line using a linear projection centered on the chip center:
	Line full;
	SkyToLocal (&full.begin, astrom, streaks->list[i].ra1, streaks->list[i].dec1);
	SkyToLocal (&full.end,   astrom, streaks->list[i].ra2, streaks->list[i].dec2);

	// clip the line to a square box with diameter = hypotenuse of the chip image centerd
	// on the chip center in tangent-plane coordinates.  skip the rest of this streak if
	// the line does not intersect this region
	if (!LineClipFull (&full, minX, minY, maxX, maxY)) {
	    continue;
	}

	// convert the end points back into ra, dec pairs:
	strkPt sky1, sky2;
	LocalToSky (&sky1, astrom, &full.begin);
	LocalToSky (&sky2, astrom, &full.end);

        if (skyToCell (&line.begin, astrom, sky1.x, sky1.y) &&
            skyToCell (&line.end,   astrom, sky2.x, sky2.y) &&
            LineClip (&line, numCols, numRows))
        {
            PixelsFromLine (pixels, &line, numCols, numRows);
            streaksOnComponent++;
        }
    }
    fprintf(stderr, "%d streaks on this component\n", streaksOnComponent);
    return pixels;
}

static void streaksFree(Streaks *streaks);

/** Read a list of streak equatorial coordinate definitions and width
    from a text file.  The format is:

    @verbatim
    numStreaks
    ra1 dec1 ra2 dec2 width
    ...
    @endverbatim

    @param[in] fileName path to streak text file to read
    @return a list of streak objects.  If there is an error in reading
            the text file, return NULL
*/

Streaks *readStreaksFile(char *fileName)
{
    int i;
    Streaks *streaks = NULL;
    FILE *file = fopen (fileName, "r");
    if (file != NULL)
    {
        streaks = psAlloc (sizeof(Streaks));
        if (fscanf (file, "%u", &streaks->size) != 1)
        {
            psFree (streaks);
            fclose (file);
            return NULL;
        }
        streaks->list = psAlloc (streaks->size * sizeof(streak));
        psMemSetDeallocator(streaks, (psFreeFunc) streaksFree);
        for (i = 0; i != streaks->size; ++i)
        {
            if (fscanf (file, "%lf %lf %lf %lf %lf",
                        &streaks->list[i].ra1, &streaks->list[i].dec1,
                        &streaks->list[i].ra2, &streaks->list[i].dec2,
                        &streaks->list[i].width) != 5)
            {
                psFree (streaks->list);
                psFree (streaks);
                streaks = NULL;
                break;
            }
        }
        fclose (file);
    }
    return streaks;
}

static void streaksFree(Streaks *streaks)
{
    psFree(streaks->list);
}
