package Kephra::File;
our $VERSION = '0.46';

use strict;
use warnings;

sub _dialog_l18n { Kephra::Config::Localisation::strings()->{dialog} }
sub _config      { Kephra::API::settings()->{file} }
sub _dir         { _config()->{current}{directory} }
#
# file events
sub savepoint_left {
	my $doc_nr = shift;
	$doc_nr = Kephra::Document::Data::current_nr() if not defined $doc_nr or ref $doc_nr;
	Kephra::Document::Data::inc_value('modified')
		unless Kephra::Document::Data::get_attribute('modified', $doc_nr);
	Kephra::Document::Data::set_attribute('modified', 1, $doc_nr);
	Kephra::App::TabBar::refresh_label($doc_nr)
		if Kephra::App::TabBar::_config()->{info_symbol};
	Kephra::EventTable::trigger('document.savepoint');
}
sub savepoint_reached {
	my $doc_nr = shift;
	$doc_nr = Kephra::Document::Data::current_nr() if not defined $doc_nr or ref $doc_nr;
	Kephra::Document::Data::dec_value('modified')
		if Kephra::Document::Data::get_attribute('modified', $doc_nr);
	Kephra::Document::Data::set_attribute('modified', 0, $doc_nr);
	Kephra::App::TabBar::refresh_label($doc_nr);
	Kephra::EventTable::trigger('document.savepoint');
}

sub can_save     { Kephra::Document::Data::attr('modified') }
sub can_save_all { Kephra::Document::Data::get_value('modified') }

sub changed_notify_check {
	my $current_doc = Kephra::Document::Data::current_nr();
	for my $file_nr ( @{ Kephra::Document::Data::all_nr() } ) {
		my $file = Kephra::Document::Data::get_file_path($file_nr);
		my $last_check = Kephra::Document::Data::get_attribute
			('did_notify', $file_nr);
		next unless $file;
		if (not -e $file) {
			next if defined $last_check and $last_check eq 'ignore';
			Kephra::Document::Change::to_number( $file_nr );
			Kephra::Dialog::notify_file_deleted( $file_nr );
			next;
		}
		my $last_change = Kephra::Document::Data::get_attribute('file_changed', $file_nr);
		my $current_age = Kephra::File::IO::get_age($file);
		if ( $last_change != $current_age) {
			next if defined $last_check
				and ( $last_check eq 'ignore' or $last_check >= $current_age);
			Kephra::Document::Change::to_number( $file_nr );
			Kephra::Document::Data::set_attribute
				('did_notify', _remember_save_moment($file_nr), $file_nr);
			Kephra::Dialog::notify_file_changed( $file_nr, $current_age );
		}
	}
	Kephra::Document::Change::to_number($current_doc) 
		unless $current_doc == Kephra::Document::Data::current_nr();
}

sub _remember_save_moment {
	my ($doc_nr) = shift || Kephra::Document::Data::current_nr();
	my $path = shift || Kephra::Document::Data::get_file_path($doc_nr);
	return unless defined $path and -e $path;
	my $age = Kephra::File::IO::get_age($path);
	Kephra::Document::Data::set_attribute('file_changed', $age, $doc_nr);
	return $age;
}

sub check_b4_overwite {
	my $file = shift;
	$file = Kephra::Document::Data::get_file_path() unless $file;
	my $allow = _config()->{save}{overwrite};
	if ( -e $file ) {
		my $frame = Kephra::App::Window::_ref();
		my $label = Kephra::Config::Localisation::strings()->{dialog};
		if ( $allow eq 'ask' ) {
			my $answer = Kephra::Dialog::get_confirm_2 (
				"$label->{general}{overwrite} $file ?",
				$label->{file}{overwrite},
				-1, -1
			);
			return 1 if $answer == &Wx::wxYES;
			return 0 if $answer == &Wx::wxNO;
		} else {
			Kephra::Dialog::info_box(
				$label->{general}{dont_allow},
				$label->{file}{overwrite}
			) unless $allow;
			return $allow;
		}
	} else { return -1 }
}
#
# drag n drop
sub add_dropped { # add all currently dnd-held files
	my ($ep, $event) = @_;
	-d $_ ? add_dir($_) : Kephra::Document::add($_) for $event->GetFiles;
}

sub add_dir{ # add all files of an dnd-held dir
	my $dir = shift;
	return until -d $dir;
	opendir (my $DH, $dir);
	my @dir_items = readdir($DH);
	closedir($DH);
	my $path;
	my $recursive = _config()->{open}{dir_recursive};

	foreach (@dir_items) {
		$path = "$dir/$_";
		if (-d $path) {
			next if not $recursive or $_ eq '.' or $_ eq '..';
			add_dir($path);
		} else { Kephra::Document::add($path) }
	}
}

#
# file menu calls
sub new  { Kephra::Document::new() }
sub open {
	# buttons dont freeze while computing
	Kephra::App::_ref()->Yield();

	# file selector dialog
	my $files = Kephra::Dialog::get_files_open( 
		_dialog_l18n()->{file}{open}, _dir(),
		$Kephra::temp{file}{filterstring}{all}
	);
	# opening selected files
	if (ref $files eq 'ARRAY') { Kephra::Document::add($_) for @$files }
}

sub open_all_of_dir {
	my $dir = Kephra::Dialog::get_dir( _dialog_l18n()->{file}{open_dir}, _dir() );
	add_dir( $dir );
}

sub reload          { reload_current(@_) } # alias
sub reload_current  {
	my $file_path = Kephra::Document::Data::get_file_path();
	my $doc_nr = Kephra::Document::Data::current_nr();
	if ($file_path and -e $file_path){
		my $ep = Kephra::App::EditPanel::_ref();
		Kephra::Document::Data::update_attributes($doc_nr);
		$ep->BeginUndoAction;
		$ep->SetText("");
		Kephra::File::IO::open_buffer( $doc_nr );
		$ep->EndUndoAction;
		$ep->SetSavePoint;
		_remember_save_moment();
		Kephra::Document::Data::evaluate_attributes();
		Kephra::App::EditPanel::Margin::autosize_line_number()
			if (Kephra::App::EditPanel::Margin::_config()->{linenumber}{autosize}
			and Kephra::App::EditPanel::Margin::_config()->{linenumber}{width} );
		Kephra::Document::Data::evaluate_attributes($doc_nr);
	} else {
	}
}
sub reload_all      { Kephra::Document::do_with_all( sub { reload_current() } ) }

sub insert {
	my $file = Kephra::Dialog::get_file_open (
		_dialog_l18n()->{file}{insert},
		_dir(),
		$Kephra::temp{file}{filterstring}{all}
	);
	Kephra::File::IO::open_buffer( Kephra::Document::Data::current_nr(), $file);
}
#
sub _save_nr {
	my $nr = shift;
	$nr = Kephra::Document::Data::current_nr() unless defined $nr;
	my $ep = Kephra::Document::Data::_ep( $nr );
	my $file = Kephra::Document::Data::get_file_path($nr);
	return until defined $nr and $ep and -e $file;
	my $save_config = _config()->{save};
	return unless $ep->GetModify == 1 or $save_config->{unchanged};
	rename $file, $file . '~' if $save_config->{tilde_backup} == 1;
	Kephra::File::IO::write_buffer( $nr );
	$ep->SetSavePoint;
	_remember_save_moment($nr);
}
sub save         { save_current(@_) }
sub save_current {
	my ($ctrl, $event) = @_;
	my $ep = Kephra::App::EditPanel::_ref();
	my $file = Kephra::Document::Data::get_file_path();
	my $save_config = _config()->{save};
	if ( $ep->GetModify == 1 or $save_config->{unchanged} ) {
		if ( $file and -e $file ) {
			if (not -w $file ) {
				my $err_msg = _dialog_l18n()->{error};
				Kephra::Dialog::warning_box(
					$err_msg->{write_protected}."\n".$err_msg->{write_protected2},
					$err_msg->{file} );
				save_as();
			} else {
				_save_nr();
				Kephra::Config::Global::eval_config_file($file)
					if $save_config->{reload_config} == 1
					and Kephra::Document::Data::get_attribute('config_file');
			}
		} else { save_as() }
	}
}

sub save_as {
	my $file = Kephra::Dialog::get_file_save(
		_dialog_l18n()->{file}{save_as},
		_dir(),
		$Kephra::temp{file}{filterstring}{all}
	);
	if ( $file and check_b4_overwite($file) ) {
		my $ep = Kephra::App::EditPanel::_ref();
		my $oldname = Kephra::Document::Data::get_file_path();
		Kephra::Document::Data::inc_value('loaded') unless $oldname;
		Kephra::Document::Data::update_attributes();
		Kephra::Document::Data::set_file_path($file);
		Kephra::File::IO::write_buffer();
		$ep->SetSavePoint();
		Kephra::Document::SyntaxMode::set('auto');
		Kephra::App::Window::refresh_title();
		Kephra::App::TabBar::refresh_current_label();
		Kephra::App::StatusBar::refresh_all_cells();
		_config()->{current}{directory} = 
			Kephra::Document::Data::get_attribute('directory');
		_remember_save_moment( );
		Kephra::EventTable::trigger('document.list');
	}
}


sub save_copy_as {
	my $file = Kephra::Dialog::get_file_save(
		_dialog_l18n()->{file}{save_copy_as},
		_dir(),
		$Kephra::temp{file}{filterstring}{all}
	);
print "---",$file,"\n";
	Kephra::File::IO::write_buffer(Kephra::Document::Data::current_nr(), $file)
		if $file and check_b4_overwite($file);
}


sub rename   {
	my $new_path_name = Kephra::Dialog::get_file_save(
		_dialog_l18n()->{file}{rename},
		_dir(),
		$Kephra::temp{file}{filterstring}{all} );
	if ($new_path_name){
		my $old_path_name = Kephra::Document::Data::get_file_path();
		rename $old_path_name, $new_path_name if $old_path_name;
		Kephra::Document::Data::set_file_path($new_path_name);
		Kephra::Document::SyntaxMode::set('auto');
		Kephra::App::Window::refresh_title();
		Kephra::App::TabBar::refresh_current_label();
		_config()->{current}{directory} = 
			Kephra::Document::Data::get_attribute('directory');
		Kephra::EventTable::trigger('document.list');
		_remember_save_moment();
	}
}


sub save_all {
	my $unsaved = can_save_all();
	return unless $unsaved;
	# save surrent if its the only
	if ($unsaved == 1 and can_save() ) {
		save_current();
	}
	#
	else {
		Kephra::Document::do_with_all( sub {
			save_current() if shift->{modified};
		} );
	}
}

sub save_all_named {
	my $unsaved = can_save_all();
	return unless $unsaved;
	my $need_save_other;
	my $cdoc_nr = Kephra::Document::Data::current_nr();
	for my $doc_nr  ( @{ Kephra::Document::Data::all_nr()} ) {
		my ($name, $mod) = @{Kephra::Document::Data::attributes(['file_name', 'modified'], $doc_nr) };
		$need_save_other = 1 if $doc_nr != $cdoc_nr and $name and $mod;
	}
	if ($need_save_other) {
		Kephra::Document::do_with_all( sub {
			my $file = shift;
			save_current() if $file->{modified} and $file->{file_name};
		} );
	} elsif (can_save() and Kephra::Document::Data::get_file_path()) {
		save_current();
	}
}

sub print {
	require Wx::Print;
	my ( $frame, $event ) = @_;
	my $ep       = Kephra::App::EditPanel::_ref();
	my $printer  = Wx::Printer->new;
	my $printout = Wx::Printout->new(
		"$Kephra::NAME $Kephra::VERSION : " . Kephra::Document::Data::file_name()
	);
	#$ep->FormatRange(doDraw,startPos,endPos,draw,target,renderRect,pageRect);
	#$printer->Print( $frame, $printout, 1 );

	$printout->Destroy;
}

sub close { close_current() }
sub close_current { close_nr( Kephra::Document::Data::current_nr() ) }
sub close_nr {
	my $doc_nr     = shift;
	my $ep         = Kephra::Document::Data::_ep($doc_nr);
	my $config     = _config()->{save};
	my $save_answer= &Wx::wxNO;

	# save text if options demand it
	if ($ep->GetModify == 1 or $config->{unchanged} eq 1) {
		if ($ep->GetTextLength > 0 or $config->{empty} eq 1) {
			if ($config->{b4_close} eq 'ask' or $config->{b4_close} eq '2'){
				my $l10n = _dialog_l18n()->{file};
				$save_answer = Kephra::Dialog::get_confirm_3
					($l10n->{save_current}, $l10n->{close_unsaved} );
			}
			return if $save_answer == &Wx::wxCANCEL;
			if ($save_answer == &Wx::wxYES or $config->{b4_close} eq '1')
				{ _save_nr($doc_nr) }
			else{ savepoint_reached($doc_nr) if $ep->GetModify }
		}
	}

	# proceed
	close_nr_unsaved($doc_nr);
}

sub close_other   {
	my $doc_nr = Kephra::Document::Data::current_nr();
	Kephra::Document::Change::to_number(0);
	$_ != $doc_nr ? close_current() : Kephra::Document::Change::to_number(1)
		for @{ Kephra::Document::Data::all_nr() };
}

sub close_all     { close_current($_) for @{ Kephra::Document::Data::all_nr() } }
sub close_unsaved { close_current_unsaved() }
sub close_current_unsaved { close_nr_unsaved( Kephra::Document::Data::current_nr()) }
sub close_nr_unsaved {
	my $doc_nr  = shift;
	my $current = Kephra::Document::Data::current_nr();
	my $ep      = Kephra::Document::Data::_ep( $doc_nr );
	my $file    = Kephra::Document::Data::get_file_path( $doc_nr );
	my $buffer  = Kephra::Document::Data::get_value( 'buffer' );
	if ($file){
		Kephra::App::EditPanel::Fold::store( $doc_nr );
		Kephra::Edit::Marker::store( $doc_nr );
	}
	Kephra::EventTable::trigger('document.close');

	# empty last document
	if ( $buffer == 1 ) {
		Kephra::Document::Data::set_value('loaded', 0);
		Kephra::Document::reset(0);
	}
	# close document
	elsif ( $buffer > 1 ) {
		# select to which file nr to jump
		my $close_last = $doc_nr == Kephra::Document::Data::last_nr();
		my $switch     = $doc_nr == $current; 
		if ($switch){
			$close_last
				? Kephra::Document::Change::to_number( $doc_nr - 1 )
				: Kephra::Document::Change::to_number( $doc_nr + 1 );
		}
		Kephra::Document::Data::dec_value('buffer');
		Kephra::Document::Data::dec_value('loaded')
			if Kephra::Document::Data::get_file_path( $doc_nr );
		Kephra::App::TabBar::delete_tab_by_doc_nr( $doc_nr );
		Kephra::Document::Data::delete_slot( $doc_nr );
		Kephra::Document::Data::set_current_nr( $doc_nr ) unless $close_last and $switch;
	}
	Kephra::App::Window::refresh_title();
	Kephra::App::EditPanel::gets_focus();

	Kephra::EventTable::trigger('document.list');
}

sub close_all_unsaved { close_current_unsaved() for @{ Kephra::Document::Data::all_nr() } }
sub close_other_unsaved {
	my $doc_nr = Kephra::Document::Data::current_nr();
	Kephra::Document::Change::to_number(0);
	$_ != $doc_nr ? close_unsaved() : Kephra::Document::Change::to_number(1)
		for @{ Kephra::Document::Data::all_nr() };
}

1;

=head1 NAME

Kephra::File - basic file menu functions

=head1 DESCRIPTION

file menu calls

drag n drop files

file save events
 
=cut