#include <unistd.h>
#include <string.h>
#include <errno.h>

#include "Scanner.h"
#include "unnamed.tif.c"

Scanner::Scanner()
{
  identity = (ScanIdentity){
    4,				// software level
  {50,60,72,75,80,90,100,120,133,144,150,160,175,180,200,216,240,300,320,360,
   400,480,600,800,900,1200,1600,1800,2400,0}, // resolutions
    2400,
    20400,			// max horizontal area
    28080			// max vert area
    };

  settings = (ScanSettings) {
    SCN_CLR_COLOR_LINE,
    75,				// main scan res
    75,				// sub scan res
    0,				// main scan off
    0,				// sub scan off
    637,			// main scan area
    877,			// sub scan area
    8,				// bpp
    SCN_HTONE_DISABLE,
    0,				// brightness
    SCN_GAMMA_CRTA,
    100,			// main zoom
    100,			// sub zoom
    SCN_CLR_CORRECT_CRT,
    SCN_SHARP_NORMAL,
    SCN_MODE_NORMAL,
    1				// lines per block
    };

  errStr[0] = '\0';
}


int
Scanner::applySettings(const ScanSettings&)
{
  return 0;
}

// Function: Scanner::getSettings
// Parameters: 
//   ScanNewSettings& s - will be filled in with the current settings
//   
// Description: Gets the current scanner settings, returning them in
// "s".  This is a new version of the function that converts the scan
// dimensions to inches rather than leaving them as raw pixel values.
// 
// Return value: 
void
Scanner::getSettings(ScanNewSettings& s) const
{
  const ScanSettings& S = settings;	// make a shorter name
  float main_res, sub_res;

  // get effective main and sub resolutions
  main_res = (float)S.main_scan_res * ((float)S.main_scan_zoom / 100.0);
  sub_res = (float)S.sub_scan_res * ((float)S.sub_scan_zoom / 100.0);
  
  s = (ScanNewSettings) {
    S.color_mode,
      S.main_scan_res,
      S.sub_scan_res,
      (float)S.main_scan_offset / main_res,
      (float)S.sub_scan_offset / sub_res,
      (float)S.main_scan_area / main_res,
      (float)S.sub_scan_area / sub_res,
      S.bits_per_pixel,
      S.halftone,
      S.brightness,
      S.gamma,
      S.main_scan_zoom,
      S.sub_scan_zoom,
      S.color_correction,
      S.sharpness,
      S.scanmode,
      S.linecounter
      };
}


void
Scanner::getIdentity(ScanNewIdentity& i) const
{
  const ScanIdentity& I = identity;	// give it a short name
  
  i.software_level = I.software_level;
  bcopy(I.resolutions, i.resolutions, sizeof(I.resolutions));
  i.max_resolution = I.max_resolution;
  i.max_horiz_area = (float)I.max_horiz_area / (float)I.max_resolution;
  i.max_vert_area = (float)I.max_vert_area / (float)I.max_resolution;
}
    
int
Scanner::applySettings(const ScanNewSettings& s)
{
  ScanSettings ns;		// new settings
  float main_res, sub_res;

  // get effective main and sub resolutions
  main_res = (float)s.main_scan_res * ((float)s.main_scan_zoom / 100.0);
  sub_res = (float)s.sub_scan_res * ((float)s.sub_scan_zoom / 100.0);
  
  ns = (ScanSettings) {
    s.color_mode,
      s.main_scan_res,
      s.sub_scan_res,
      (int)(s.main_scan_offset * main_res),
      (int)(s.sub_scan_offset * sub_res),
      (int)(s.main_scan_area * main_res),
      (int)(s.sub_scan_area * sub_res),
      s.bits_per_pixel,
      s.halftone,
      s.brightness,
      s.gamma,
      s.main_scan_zoom,
      s.sub_scan_zoom,
      s.color_correction,
      s.sharpness,
      s.scanmode,
      s.linecounter
      };

  return applySettings(ns);
}

int
Scanner::scanSize() const
{
  return IMG_SIZE;
}

int
Scanner::startScan(const char *fname, int (*clbk)(int))
{
  if (clbk) {			// simulate getting a picture
    for (int i = 0; i < 500; i++) {
      usleep(100);
      if (clbk(i))
	return 0;
    }
  } else {
    cout << "Scanning an image to " << fname << endl;
    sleep(5);
    return 0;
  }
}

int
Scanner::initScan(const char *fname)
{
  bytesRead = 0;
  if ((outf = fopen(fname, "w")) == NULL) {
    strcpy(errStr, strerror(errno));
    return -1;
  }
  inp = img_data;
  return 0;
}

int
Scanner::scanBlock(bool cancel)
{
  // usleep(50);
  int readBytes = (bytesRead + 10) > IMG_SIZE ? (IMG_SIZE-bytesRead) : 10;
  readBytes = fwrite(inp, 1, readBytes, outf);
  bytesRead += readBytes;
  inp += readBytes;
  if (readBytes == 0 || bytesRead >= IMG_SIZE || cancel) {
    fclose(outf);
    return 0;
  }
  else 
    return readBytes;
}
