/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 
/* vim: set ts=2 et sw=2 tw=80: */
/*
  Copyright 2013-2021 Stephan Beal (https://wanderinghorse.net).

  Derived heavily from previous work:

  Copyright (c) 2013 D. Richard Hipp (https://www.hwaci.com/drh/)

  
  This program is free software; you can redistribute it and/or
  modify it under the terms of the Simplified BSD License (also
  known as the "2-Clause License" or "FreeBSD License".)
  
  This program is distributed in the hope that it will be useful,
  but without any warranty; without even the implied warranty of
  merchantability or fitness for a particular purpose.
  
  *****************************************************************************
  This file creates ZIP files from fossil repository content.
*/

#include "fossil-scm/fossil-cli.h" /* Fossil App mini-framework */

static void fapp_local_help(){
  printf("Usage:\n\t%s [options] CHECKIN_VERSION OUTPUT_FILE\n\n", fcli.appName);

  puts("Creates ZIP files from Fossil repository checkins. Options:\n");

  puts("\t-r|--root=STRING causes all ZIPped files to be packed in "
       "a directory with that name. By default a root directory name "
       "is generated from the repo's 'project-name' config option and "
       "the UUID of version being zipped.\n");

  puts("\t-V|--verbose enables informational output. Use twice (or -VV) "
       "to get even more output (list of files being zipped).\n");

  puts("\t-q|--quiet Suppresses all non-error output. Trumped by -V.");

}

static int vbose = 0;

static int fsl_card_F_visitor_progress(fsl_card_F const * fc,
                                  void * state){
  ++(*((int*)state));
  if(vbose>1){
    f_out("Adding: %.12s %s\n", fc->uuid, fc->name);
  }
  return 0;
}

int main(int argc, char * const * argv ){
  int rc = 0;
  const char * sym = NULL;
  const char * fileName = NULL;
  const char * rootDir = NULL;
  fsl_cx * f;
  fsl_db * db;
  char noRoot;
  fsl_uuid_str uuid = NULL;
  int fileCounter = 0;
  fcli.appHelp = fapp_local_help;
  rc = fcli_setup(argc, argv);
  if(FSL_RC_BREAK==rc) /* --help */ return 0;
  else if(rc) goto end;
  vbose = fcli_is_verbose();
  f = fcli_cx();
  db = fsl_needs_repo(f);
  if(!db){
    rc = FSL_RC_NOT_A_REPO;
    goto end;
  }

  if(!vbose){
    vbose = fcli_flag2("q", "quiet", NULL) ? 0 : 1;
  }

  fcli_flag2("root", "r", &rootDir);

  noRoot = fcli_flag("no-root",NULL) /* undocumented flag, for testing only.*/;

  if(fcli_has_unused_flags(0)) goto end;

  sym = fcli_next_arg(1);
  fileName = fcli_next_arg(1);
  if(!sym || !*sym || !fileName || !*fileName){
    rc = fcli_err_set(FSL_RC_MISUSE,
                      "Usage: %s [options] CHECKIN_VERSION OUTPUT_FILE"
                      "\nOr try --help.",
                      fcli.appName);
    goto end;
  }

  rc = fsl_sym_to_uuid(f, sym, FSL_SATYPE_CHECKIN, &uuid, NULL);
  if(rc) goto end;

  if(!noRoot && !rootDir){
    char * pname;
    char * pz;
    pz = pname = fsl_config_get_text(f, FSL_CONFDB_REPO,
                                     "project-name", NULL);
    /* Translate unusual characters to underscores... */
    for( ; *pz; ++pz ){
      if('_'!=*pz && '-'!=*pz
         && !fsl_isalnum(*pz)){
        *pz = '_';
      }
    }
    pz = fsl_mprintf("%s-%.12s", pname, uuid);
    fcli_fax(pz);
    rootDir = pz;
    fsl_free(pname);
  }

  if(vbose){
    f_out("Extracting repository version %.12s to file %s...\n",
          uuid, fileName);
  }
  rc = fsl_repo_zip_sym_to_filename(f, sym, noRoot ? NULL : rootDir,
                                    fileName,
                                    vbose ? fsl_card_F_visitor_progress : NULL,
                                    &fileCounter);
  if(vbose && !rc){
    f_out("%d file(s) zipped to %s\n", fileCounter, fileName);
  }
  end:
  fsl_free(uuid);
  return fcli_end_of_main(rc);
}
