package UR::Namespace::Command::Update::TabCompletionSpec;

use strict;
use warnings;

use UR;
our $VERSION = "0.41"; # UR $VERSION;
use IO::File;

UR::Object::Type->define(
    class_name => __PACKAGE__,
    is => 'UR::Namespace::Command::Base',
    has => [
        classname => {
            is => 'Text',
            shell_args_position => 1,
            doc => 'The base class to use as trunk of command tree, e.g. UR::Namespace::Command',
        },
        output => {
            is => 'Text',
            is_optional => 1,
            doc => 'Override output location of the opts spec file.',
        },
    ]
);


sub help_brief {
    "Creates a .opts file beside class/module passed as argument, e.g. UR::Namespace::Command.";
}

sub create {
    my $class = shift;

    my $bx = $class->define_boolexpr(@_);
    if($bx->specifies_value_for('classname') and !$bx->specifies_value_for('namespace_name')) {
        my $classname = $bx->value_for('classname');
        my($namespace) = ($classname =~ m/^(\w+)::/);
        $bx = $bx->add_filter(namespace_name => $namespace) if $namespace;
    }
    return $class->SUPER::create($bx);
}



sub is_sub_command_delegator { 0; }

sub execute {
    my $self = shift;
    my $class = $self->classname;
   
    eval {
        require Getopt::Complete;
        require Getopt::Complete::Cache;
    };
    if ($@) {
        die "Errors using Getopt::Complete.  Do you have Getopt::Complete installed?  If not try 'cpanm Getopt::Complete'";
    }

    eval "use above '$class';";
    if ($@) {
        $self->error_message("Unable to use above $class.\n$@");
        return;
    }

    (my $module_path) = Getopt::Complete::Cache->module_and_cache_paths_for_package($class, 1);
    my $cache_path = $module_path . ".opts";
    if (-s $cache_path) {
        rename($cache_path, "$cache_path.bak");
    }
    unless ($self->output) {
        $self->output($cache_path);
    }
    $self->status_message("Generating " . $self->output . " file for $class.");
    $self->status_message("This may take some time and may generate harmless warnings...");

    my $fh;
    $fh = IO::File->new('>' . $self->output) || die "Cannot create file at " . $self->output . "\n";
    
    if ($fh) {
        my $src = Data::Dumper::Dumper($class->resolve_option_completion_spec());
        $src =~ s/^\$VAR1/\$$class\:\:OPTS_SPEC/;
        $fh->print($src);
    }
    if (-s $cache_path) {
        $self->status_message("\nOPTS_SPEC file created at $cache_path");
        unlink("$cache_path.bak");
    } else {
        if (-s "$cache_path.bak") {
            $self->error_message("$cache_path is 0 bytes, reverting to previous");
            rename("$cache_path.bak", $cache_path);
        } else {
            $self->error_message("$cache_path is 0 bytes and no backup exists, removing file");
            unlink($cache_path);
        }
    }
}

1;
