/*
 * This file Copyright (C) Mnemosyne LLC
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation.
 *
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 *
 * $Id: create.c 12225 2011-03-24 22:57:39Z jordan $
 */

#include <errno.h>
#include <stdio.h> /* fprintf() */
#include <stdlib.h> /* EXIT_FAILURE */
#include <unistd.h> /* getcwd() */

#include <libtransmission/transmission.h>
#include <libtransmission/makemeta.h>
#include <libtransmission/tr-getopt.h>
#include <libtransmission/utils.h>
#include <libtransmission/version.h>

#define MY_NAME "transmission-create"

#define MAX_TRACKERS 128
static tr_tracker_info trackers[MAX_TRACKERS];
static int trackerCount = 0;
static bool isPrivate = false;
static bool showVersion = false;
const char * comment = NULL;
const char * outfile = NULL;
const char * infile = NULL;

static tr_option options[] =
{
  { 'p', "private", "Allow this torrent to only be used with the specified tracker(s)", "p", 0, NULL },
  { 'o', "outfile", "Save the generated .torrent to this filename", "o", 1, "<file>" },
  { 'c', "comment", "Add a comment", "c", 1, "<comment>" },
  { 't', "tracker", "Add a tracker's announce URL", "t", 1, "<url>" },
  { 'V', "version", "Show version number and exit", "V", 0, NULL },
  { 0, NULL, NULL, NULL, 0, NULL }
};

static const char *
getUsage( void )
{
    return "Usage: " MY_NAME " [options] <file|directory>";
}

static int
parseCommandLine( int argc, const char ** argv )
{
    int c;
    const char * optarg;

    while(( c = tr_getopt( getUsage( ), argc, argv, options, &optarg )))
    {
        switch( c )
        {
            case 'V': showVersion = true; break;
            case 'p': isPrivate = true; break;
            case 'o': outfile = optarg; break;
            case 'c': comment = optarg; break;
            case 't': if( trackerCount + 1 < MAX_TRACKERS ) {
                          trackers[trackerCount].tier = trackerCount;
                          trackers[trackerCount].announce = (char*) optarg;
                          ++trackerCount;
                      }
                      break;
            case TR_OPT_UNK: infile = optarg; break;
            default: return 1;
        }
    }

    return 0;
}

static char*
tr_getcwd( void )
{
    char * result;
    char buf[2048];
#ifdef WIN32
    result = _getcwd( buf, sizeof( buf ) );
#else
    result = getcwd( buf, sizeof( buf ) );
#endif
    if( result == NULL )
    {
        fprintf( stderr, "getcwd error: \"%s\"", tr_strerror( errno ) );
        *buf = '\0';
    }
    return tr_strdup( buf );
}

int
main( int argc, char * argv[] )
{
    char * out2 = NULL;
    tr_metainfo_builder * b = NULL;

    tr_setMessageLevel( TR_MSG_ERR );

    if( parseCommandLine( argc, (const char**)argv ) )
        return EXIT_FAILURE;

    if( showVersion ) {
        fprintf( stderr, MY_NAME" "LONG_VERSION_STRING"\n" );
        return 0;
    }

    if( !infile )
    {
        fprintf( stderr, "ERROR: No input file or directory specified.\n" );
        tr_getopt_usage( MY_NAME, getUsage( ), options );
        fprintf( stderr, "\n" );
        return EXIT_FAILURE;
    }

    if( outfile == NULL )
    {
        char * base = tr_basename( infile );
        char * end = tr_strdup_printf( "%s.torrent", base );
        char * cwd = tr_getcwd( );
        outfile = out2 = tr_buildPath( cwd, end, NULL );
        tr_free( cwd );
        tr_free( end );
        tr_free( base );
    }

    if( !trackerCount )
    {
        if( isPrivate )
        {
            fprintf( stderr, "ERROR: no trackers specified for a private torrent\n" );
            return EXIT_FAILURE;
        }
        else
        {
            printf( "WARNING: no trackers specified\n" );
        }
    }

    printf( "Creating torrent \"%s\" ...", outfile );
    fflush( stdout );

    b = tr_metaInfoBuilderCreate( infile );
    tr_makeMetaInfo( b, outfile, trackers, trackerCount, comment, isPrivate );
    while( !b->isDone ) {
        tr_wait_msec( 500 );
        putc( '.', stdout );
        fflush( stdout );
    }

    putc( ' ', stdout );
    switch( b->result ) {
        case TR_MAKEMETA_OK:        printf( "done!" ); break;
        case TR_MAKEMETA_URL:       printf( "bad announce URL: \"%s\"", b->errfile ); break;
        case TR_MAKEMETA_IO_READ:   printf( "error reading \"%s\": %s", b->errfile, tr_strerror(b->my_errno) ); break;
        case TR_MAKEMETA_IO_WRITE:  printf( "error writing \"%s\": %s", b->errfile, tr_strerror(b->my_errno) ); break;
        case TR_MAKEMETA_CANCELLED: printf( "cancelled" ); break;
    }
    putc( '\n', stdout );

    tr_metaInfoBuilderFree( b );
    tr_free( out2 );
    return 0;
}
