#ifdef __CYGWIN__
#include <Windows.h>
#endif
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#include <errno.h>

#define LOG 0

#include "pathcompress.h"

inline void do_nothing(char* fmt, ...) { }

#ifndef Dprintf

#define DEBUG 0

#if DEBUG
#define Dprintf printf
#else
#define Dprintf do_nothing
#endif
#endif

#if 1
#define DDprintf Dprintf
#else
#define DDprintf do_nothing
#endif

#if LOG
FILE* log = NULL;
#endif

#define PATH_LEN 2048

char pathcompress_cwd[PATH_LEN];
char* pathcompress_working_dir(char *p) {
  if (
      (p[0]=='.' && p[1]=='/')
      || (p[0]=='.' && p[1]=='.' && p[2]=='/')
      || (p[0]!='/')
  ) {
    getcwd(pathcompress_cwd, sizeof(pathcompress_cwd));
    sprintf(pathcompress_cwd+strlen(pathcompress_cwd), "/");
  } else {
    sprintf(pathcompress_cwd, "%s", "");
  }
  //Dprintf("pathcompress_working_dir(%s)=%s\n", p, pathcompress_cwd);
  return pathcompress_cwd;
}

int pathcompress_find_name(char* wd, char* filename, char* shortname, char* longname) {
#ifdef __CYGWIN__
  WIN32_FIND_DATA finddata;
  HANDLE hFind;
  char path[PATH_LEN];
  char win32_path[PATH_LEN];
  if (wd[strlen(wd)-1]!='/') {
    sprintf(path, "%s/%s", wd, filename);
  } else {
    sprintf(path, "%s%s", wd, filename);
  }
  cygwin_conv_to_full_win32_path(path, win32_path);
  //Dprintf("win32_path = %s\n", win32_path);
  hFind = FindFirstFile(win32_path, &finddata);
  if (hFind != INVALID_HANDLE_VALUE) {
    if (shortname != NULL) {
      if (finddata.cAlternateFileName[0] != '\0') {
	sprintf(shortname, "%s", finddata.cAlternateFileName);
      } else {
	sprintf(shortname, "%s", filename);
      }
      Dprintf("=%s\n", shortname);
    }
    if (longname != NULL) {
      sprintf(longname, finddata.cFileName);
      Dprintf("=%s\n", longname);
    }
    FindClose(hFind);
    return 1;
  } else {
    if (shortname != NULL) {
      sprintf(shortname, "%s", filename);
    }
    if (longname != NULL) {
      sprintf(longname, "%s", filename);
    }
    Dprintf("=NULL");
    return 1;
  }
#endif
  return 0; /* not implemented */
}

int pathcompress_find_shortname(char* wd, char* filename, char* shortname) {
  //Dprintf("pathcompress_find_shortname(%s,%s)", wd, filename);
  return pathcompress_find_name(wd, filename, shortname, NULL);
}

int pathcompress_find_longname(char* wd, char* filename, char* longname) {
  //Dprintf("pathcompress_find_longname(%s,%s)", wd, filename);
  return pathcompress_find_name(wd, filename, NULL, longname);
}

char* pathcompress_process_path(char* path, char* compressed, char* uncompressed) {
  char compressed_wd[PATH_LEN];
  char compressed_path[PATH_LEN]="";
  char uncompressed_path[PATH_LEN]="";
  char filename[PATH_LEN];
  char longname[PATH_LEN];
  char shortname[PATH_LEN];
  char* c = compressed;
  char* u = uncompressed;
  char* p = path;
  char* f;
  char* w;
  char* wd;
  int compressing = compressed == NULL?0:1;
  if (c == NULL) c = compressed_path;
  if (u == NULL) u = uncompressed_path;

  wd = pathcompress_working_dir(path);
  w = compressed_wd;
  w += sprintf(w, "%s", wd);
  *w = '\0';

  while (*p != '\0') {
    f = filename;
    if ((p[0] == '.') && (p[1] == '.') && ((p[2] == '\0') || (p[2] == '/'))) {
      *u++ = *c++ = *p++;
      *u++ = *c++ = *p++;
      *u++ = *c++ = *p++;
      while ((w[-1] != '/' ) && (w > compressed_wd)) {
	w--;
      }
      *u = *c = *w = '\0';
      continue;
    } else if ((p[0] == '.') && (p[1] == '/')) {
      *u++ = *c++ = *p++;
      *u++ = *c++ = *p++;
      *u = *c = '\0';
      continue;
    } else if ((p[0] == '.') && (p[1] == '\0')){
      *u++ = *c++ = *w++ = *p++;
      *u = *c = *w = '\0';
      continue;
    } else if (p[0] == '/') {
      while (p[1] == '/') p++;
      *u++ = *c++ = *w++ = *p++;
      *u = *c = *w = '\0';
      continue;
    }
    while ((*p != '/') && (*p != '\0')) {
      *f++ = *p++;
    }
    *f = '\0';
    if (compressing) {
      if (pathcompress_find_shortname(compressed_wd, filename, shortname)) {
	c += sprintf(c, "%s", shortname);
	w += sprintf(w, "%s", shortname);
	u += sprintf(w, "%s", filename);
	*u = *c = *w = '\0';
      }
    } else {
      if (pathcompress_find_longname(compressed_wd, filename, longname)) {
	c += sprintf(c, "%s", filename);
	u += sprintf(u, "%s", longname);
	w += sprintf(w, "%s", filename);
	*u = *c = *w = '\0';
      }
    }
  }
  Dprintf("=%s", compressed==NULL?uncompressed:compressed);
  if (compressed == NULL) {
    return uncompressed;
  } else if (strlen(compressed)>240) {
    return NULL;
  } else {
    return compressed;
  }
}

char* pathcompress_uncompress_path(char* path, char* uncompressed) {
  Dprintf("pathcompress_uncompress_path(%s)", path);
  return pathcompress_process_path(path, NULL, uncompressed);
}

char* pathcompress_compress_path(char* path, char* compressed) {
  Dprintf("pathcompress_compress_path(%s)", path);
  return pathcompress_process_path(path, compressed, NULL);
}

void pathcompress_add_path(char* path, char* abspath) {
}

void pathcompress_remove_path(char* path) {
}

void pathcompress_add_pathid(char* path) {
}

void pathcompress_update_pathid(char* path) {
}
