#include "image.h"

// ===================================================================================================
// ===================================================================================================

void Compress(const Image<Color> &input, 
              Image<bool> &occupancy, Image<Color> &hash_data, Image<Offset> &offset) {
  
  // you must implement this function

}

// ===================================================================================================
// ===================================================================================================

void UnCompress(const Image<bool> &occupancy, const Image<Color> &hash_data, const Image<Offset> &offset, 
                Image<Color> &output) {

  // you must implement this function

}

// ===================================================================================================
// ===================================================================================================

void Compare(const Image<Color> &input1, const Image<Color> &input2, 
             Image<bool> &output) {

  // confirm that the files are the same size
  if (input1.Width() != input2.Width() || input1.Height() != input2.Height()) {
    std::cerr << "Error: can't compare images of different dimensions: " 
              << input1.Width() << "x" << input1.Height() << " vs " 
              << input2.Width() << "x" << input2.Height() << std::endl;
  } else {

    // prepare space for the difference image
    output.Allocate(input1.Width(),input1.Height());
    int count = 0;
    for (int i = 0; i < input1.Width(); i++) {
      for (int j = 0; j < input1.Height(); j++) {
        Color c1 = input1.GetPixel(i,j);
        Color c2 = input2.GetPixel(i,j);
        if (c1.r == c2.r && c1.g == c2.g && c1.b == c2.b)
          output.SetPixel(i,j,true);
        else {
          count++;
          output.SetPixel(i,j,false);
        }
      }      
    }     

    // output the number of pixels that don't match
    if (count == 0) {
      std::cout << "The images are identical." << std::endl;
    } else {
      std::cout << "The images differ at " << count << " pixel(s)." << std::endl;
    }
  }
}

// ===================================================================================================
// ===================================================================================================

void usage(char* executable) {
  std::cerr << "Usage:  3 options" << std::endl;
  std::cerr << "  1)  " << executable << " compress input.ppm occupancy.pbm data.ppm offset.offset" << std::endl;
  std::cerr << "  2)  " << executable << " uncompress occupancy.pbm data.ppm offset.offset output.ppm" << std::endl;
  std::cerr << "  3)  " << executable << " compare input1.ppm input2.ppm output.pbm" << std::endl;
  exit(1);
}

// ===================================================================================================
// ===================================================================================================

int main(int argc, char* argv[]) {
  if (argc < 2) usage(argv[0]);

  if (argv[1] == std::string("compress")) {

    if (argc != 6) usage(argv[0]); 
    // the original image:
    Image<Color> input;
    if (!input.Load(argv[2])) usage(argv[0]);
    // 3 files form the compressed representation:
    Image<bool> occupancy;
    Image<Color> hash_data;
    Image<Offset> offset;
    Compress(input,occupancy,hash_data,offset);
    // save the compressed representation
    if (!occupancy.Save(argv[3])) usage(argv[0]);
    if (!hash_data.Save(argv[4])) usage(argv[0]);
    if (!offset.Save(argv[5])) usage(argv[0]);
    
  } else if (argv[1] == std::string("uncompress")) {

    if (argc != 6) { usage(argv[0]); exit(1); }
    // the compressed representation:
    Image<bool> occupancy;
    Image<Color> hash_data;
    Image<Offset> offset;
    if (!occupancy.Load(argv[2])) usage(argv[0]);
    if (!hash_data.Load(argv[3])) usage(argv[0]);
    if (!offset.Load(argv[4])) usage(argv[0]);
    // the reconstructed image
    Image<Color> output;
    UnCompress(occupancy,hash_data,offset,output);
    // save the reconstruction
    if (!output.Save(argv[5])) usage(argv[0]);
    
  } else if (argv[1] == std::string("compare")) {

    if (argc != 5) { usage(argv[0]); exit(1); }
    // the original images
    Image<Color> input1;
    Image<Color> input2;
    if (!input1.Load(argv[2])) usage(argv[0]);
    if (!input2.Load(argv[3])) usage(argv[0]);
    // the difference image
    Image<bool> output;
    Compare(input1,input2,output);
    // save the difference
    if (!output.Save(argv[4])) usage(argv[0]);

  } else {
    usage(argv[0]);
  }
}

