package Kephra::App::TabBar;
our $VERSION = '0.18';

use strict;
use warnings;

# internal data
my $notebook;
sub _ref    { $notebook = ref $_[0] eq 'Wx::AuiNotebook' ? $_[0] : $notebook }
sub _config { my $cfg = Kephra::API::settings(); $cfg->{app}{tabbar} if keys %$cfg }

my @doc2tab_pos; # tab index numbers in doc order
my @tab2doc_pos; # doc numbers in tab index order
my @doc2vis_pos; # visible tab pos number in doc order
my @vis2doc_pos; # doc numbers in visible tab order
sub _update_doc_pos  {
	@doc2tab_pos = ();
	@doc2vis_pos = ();
	$doc2tab_pos[ $tab2doc_pos[$_] ] = $_ for 0 .. $#tab2doc_pos;
	$doc2vis_pos[ $vis2doc_pos[$_] ] = $_ for 0 .. $#vis2doc_pos;
}
sub _validate_doc_nr { &Kephra::Document::Data::validate_doc_nr }
sub _doc2tab_pos {
	my $nr = _validate_doc_nr(shift);
	return $nr == -1 ? -1 : $doc2tab_pos[$nr];
}
sub _tab2doc_pos {
	my $nr = _validate_doc_nr(shift);
	return $nr == -1 ? -1 : $tab2doc_pos[$nr];
}
sub _vis2doc_pos {
	my $nr = _validate_doc_nr(shift);
	return $nr == -1 ? -1 : $vis2doc_pos[$nr];
}
sub _doc2vis_pos {
	my $nr = _validate_doc_nr(shift);
	return $nr == -1 ? -1 : $doc2vis_pos[$nr];
}
sub _move_vis_pos {
	my $from = _validate_doc_nr(shift);
	my $to = _validate_doc_nr(shift);
	return if $from == -1 or $to == -1;
	my $doc_nr = splice @vis2doc_pos, $from, 1;
	splice @vis2doc_pos, $to, 0, $doc_nr;
	_update_doc_pos();
#print "vis_order: @vis2doc_pos, tab_order: @tab2doc_pos\n";
#print $notebook->GetPageIndex( Kephra::Document::Data::_ep($_) )."\n" for @{Kephra::Document::Data::all_nr()};
}
sub _move_tab_pos {
	my $from = _validate_doc_nr(shift);
	my $to = _validate_doc_nr(shift);
	return if $from == -1 or $to == -1;
	my $doc_nr = splice @tab2doc_pos, $from, 1;
	splice @tab2doc_pos, $to, 0, $doc_nr;
	_update_doc_pos(); #print "taborder: @tab2doc_pos, doc_order: @doc_order\n";
#print $notebook->GetPageIndex( Kephra::Document::Data::_ep($_) )."\n" for @{Kephra::Document::Data::all_nr()};
}
sub _remove_tab {
	my $tab_nr = _validate_doc_nr(shift);
	return if $tab_nr == -1;
	my $doc_nr = $tab2doc_pos[$tab_nr];
	my $vis_nr = $doc2vis_pos[$doc_nr];
	splice @tab2doc_pos, $tab_nr, 1;
	splice @vis2doc_pos, $vis_nr, 1;
	for (0 .. $#tab2doc_pos) {$tab2doc_pos[$_]-- if $tab2doc_pos[$_] > $doc_nr}
	for (0 .. $#vis2doc_pos) {$vis2doc_pos[$_]-- if $vis2doc_pos[$_] > $doc_nr}
	_update_doc_pos();
#print "vis_order: @vis2doc_pos, tab_order: @tab2doc_pos\n";
}
#
# basic toolbar creation
#
sub create {
	# create notebook if there is none
	my $notebook = _ref();
	$notebook->Destroy if defined $notebook;
	$notebook = Wx::AuiNotebook->new
		(Kephra::App::Window::_ref(),-1, [0,0], [-1,23],
		&Wx::wxAUI_NB_TOP | &Wx::wxAUI_NB_SCROLL_BUTTONS);
	_ref($notebook);
	#Wx::Event::EVT_LEFT_UP( $notebook, sub {
		#my ($tabs, $event) = @_; print "\n left up\n";
		#Kephra::Document::Data::set_value('b4tabchange', $tabs->GetSelection);
		#$event->Skip;
	#});
	#Wx::Event::EVT_LEFT_DOWN( $notebook, sub {
		#my ($tabs, $event) = @_; print "\n left down\n";
		#Kephra::Document::Change::switch_back()
			#if Kephra::Document::Data::get_value('b4tabchange')==$tabs->GetSelection;
		#$event->Skip;
	#});
	my $begin_drag_index;
	Wx::Event::EVT_AUINOTEBOOK_BEGIN_DRAG($notebook, -1, sub {
		$begin_drag_index = $_[1]->GetSelection;
	});	
	Wx::Event::EVT_AUINOTEBOOK_END_DRAG($notebook, -1, sub {
		_move_vis_pos($begin_drag_index, $_[1]->GetSelection);
		#rotate_tab($_[1]->GetSelection - $begin_drag_index);
		Kephra::App::EditPanel::gets_focus();
		Kephra::EventTable::trigger('document.list');
	});
	Wx::Event::EVT_AUINOTEBOOK_PAGE_CHANGED( $notebook, -1, sub {
		my ( $bar, $event ) = @_;
		my $new_nr = _tab2doc_pos( $event->GetSelection );
		my $old_nr = _tab2doc_pos( $event->GetOldSelection );
#print "=begin change ".$event->GetSelection." page ; docs: $old_nr -> $new_nr\n";
		#print "=end change page $nr\n";
		Kephra::Document::Change::to_number( $new_nr, $old_nr);
		Kephra::App::EditPanel::gets_focus();
		$event->Skip;
	});
	Wx::Event::EVT_AUINOTEBOOK_PAGE_CLOSE( $notebook, -1, sub {
		my ( $bar, $event ) = @_;
		Kephra::File::close_nr( _tab2doc_pos($event->GetSelection) );
		$event->Veto;
	});
}

sub apply_settings {
	my $notebook = _ref();
	# Optional middle click over the tabs
	if ( _config()->{middle_click} ) {
		Wx::Event::EVT_MIDDLE_UP(
			$notebook,
			Kephra::CommandList::get_cmd_property( _config()->{middle_click},'call')
		);
	}
	my $style = $notebook->GetWindowStyleFlag();
	$style |= &Wx::wxAUI_NB_TAB_MOVE if _config->{movable_tabs};
	$style |= &Wx::wxAUI_NB_WINDOWLIST_BUTTON if _config->{tablist_button};
	if    (_config->{close_button} =~ /all/){ $style |= &Wx::wxAUI_NB_CLOSE_ON_ALL_TABS}
	elsif (_config->{close_button} =~ /one/){ $style |= &Wx::wxAUI_NB_CLOSE_BUTTON}
	elsif (_config->{close_button} =~ /current/){$style |= &Wx::wxAUI_NB_CLOSE_ON_ACTIVE_TAB}
	elsif (_config->{close_button} =~ /active/) {$style |= &Wx::wxAUI_NB_CLOSE_ON_ACTIVE_TAB}
	# wxAUI_NB_TAB_SPLIT wxAUI_NB_TAB_EXTERNAL_MOVE
	$notebook->SetWindowStyle( $style );
	show();
}
#
# tab functions
#
sub add_edit_tab  {
	my $current_nr = Kephra::Document::Data::current_nr();
	my $doc_nr = shift || $current_nr;
	my $config = _config();
	my $mode = (ref $config and defined $config->{insert_new_tab})
		? $config->{insert_new_tab}
		: 'rightmost';
	my $vis_pos;
	$vis_pos = 0             if $mode eq 'leftmost';
	$vis_pos = $current_nr   if $mode eq 'left';
	$vis_pos = $current_nr+1 if $mode eq 'right';
	$vis_pos = $doc_nr       if $mode eq 'rightmost';
	my $stc = Kephra::App::EditPanel::new();
	Kephra::Document::Data::set_attribute('ep_ref', $stc, $doc_nr);
	#my $panel = Wx::Panel->new( $notebook, -1);
	#$stc->Reparent($panel);
	#my $sizer = Wx::BoxSizer->new( &Wx::wxVERTICAL );
	#$sizer->Add( $stc, 1, &Wx::wxGROW, 0);
	#$panel->SetSizer($sizer);
	#$panel->SetAutoLayout(1);
	#$notebook->Freeze(); #$notebook->Thaw();
	my $notebook = _ref();
	#$notebook->InsertPage( $vis_pos, $stc, '', 0 );
	$notebook->AddPage( $stc, '', 0 );
	$notebook->Layout();
	$stc->Layout();
	splice @tab2doc_pos, $doc_nr, 0, $doc_nr; # splice @tab2doc_pos, $vis_pos, 0, $doc_nr;
	splice @vis2doc_pos, $doc_nr, 0, $doc_nr; # splice @vis2doc_pos, $vis_pos, 0, $doc_nr;
	_update_doc_pos();
	return $stc;
}

sub add_panel_tab {
	my $doc_nr = shift || Kephra::Document::Data::current_nr();
	my $panel = shift;
	return unless defined $panel and substr(ref $panel, 0, 4) eq 'Wx::';
	$panel->Reparent($notebook);
	$notebook->InsertPage($panel, '', 0 ); # attention no $pos yet
	return $panel;
}

sub raise_tab_by_doc_nr { raise_tab_by_tab_nr( _doc2tab_pos(shift) ) }
sub raise_tab_by_vis_nr { raise_tab_by_tab_nr( _doc2tab_pos( _vis2doc_pos(shift)))}
sub raise_tab_by_tab_nr {
	my $nr = shift;
	$notebook->SetSelection($nr) unless $nr == $notebook->GetSelection;
}
sub raise_tab_left  {
	my $vis_nr = _doc2vis_pos( Kephra::Document::Data::current_nr() );
	raise_tab_by_vis_nr( Kephra::Document::Data::next_nr(-1, $vis_nr) );
}
sub raise_tab_right {
	my $vis_nr = _doc2vis_pos( Kephra::Document::Data::current_nr() );
	raise_tab_by_vis_nr( Kephra::Document::Data::next_nr(1, $vis_nr) );
}
sub rotate_tab_left { rotate_tab(-1) }
sub rotate_tab_right{ rotate_tab( 1) }
sub rotate_tab {
	return unless _config()->{movable_tabs};
	my $rot_step = shift;
	my $doc_nr = Kephra::Document::Data::current_nr();
	my $old_tab_pos = _doc2tab_pos( $doc_nr );
	my $old_vis_pos = _doc2vis_pos( $doc_nr );
	my $new_vis_pos = Kephra::Document::Data::next_nr($rot_step, $old_vis_pos);
	my $notebook = _ref();
	my $label = $notebook->GetPageText( $old_tab_pos );
	my $stc = Kephra::Document::Data::_ep($doc_nr);
	$notebook->RemovePage( $old_tab_pos );
	$notebook->InsertPage( $new_vis_pos, $stc, $label, 0 );
	_move_tab_pos( $old_tab_pos, $new_vis_pos );
	_move_vis_pos( $old_vis_pos, $new_vis_pos );
	raise_tab_by_vis_nr($new_vis_pos);
	Kephra::EventTable::trigger('document.list');
}

sub delete_tab_by_doc_nr { delete_tab_by_tab_nr( _doc2tab_pos(shift) ) }
sub delete_tab_by_tab_nr { 
	my $tab_nr = shift;
	my $doc_nr = _tab2doc_pos($tab_nr);
	my $notebook = _ref();
#print "delete tab $tab_nr \n";
	my $stc = Kephra::Document::Data::_ep($doc_nr);
#print $notebook->GetSelection."current, del tab nr $nr\n";
	_remove_tab($tab_nr);
	$notebook->RemovePage($tab_nr); # DeletePage,RemovePage
	$stc->Destroy(); # $xw->Reparent( undef );
}
#
# refresh the label of given number
#
sub refresh_label {
	my $doc_nr = shift;
	$doc_nr = Kephra::Document::Data::current_nr() unless defined $doc_nr;
	return unless _validate_doc_nr($doc_nr) > -1;

	my $config   = _config();
	my $untitled = Kephra::Config::Localisation::strings()->{app}{general}{untitled};
	my $label    = Kephra::Document::Data::get_attribute
					( $config->{file_info}, $doc_nr ) || "<$untitled>";

	# shorten too long filenames
	my $max_width = $config->{max_tab_width};
	if ( length($label) > $max_width and $max_width > 7 ) {
		$label = substr( $label, 0, $max_width - 3 ) . '...';
	}
	# set config files in square brackets
	if (    $config->{mark_configs}
		and Kephra::Document::Data::get_attribute('config_file', $doc_nr)
		and Kephra::API::settings()->{file}{save}{reload_config}              ) {
		$label = '$ ' . $label;
	}
	$label = ( $doc_nr + 1 ) . ' ' . $label if $config->{number_tabs};
	Kephra::Document::Data::set_attribute('label', $label);
	if ( $config->{info_symbol} ) {
		$label .= ' #' if Kephra::Document::Data::get_attribute('editable');
		$label .= ' *' if Kephra::Document::Data::get_attribute('modified');
	}
	$notebook->SetPageText( _doc2tab_pos($doc_nr), $label );
}

sub refresh_current_label { refresh_label(Kephra::Document::Data::current_nr()) }
sub refresh_all_label {
	if ( Kephra::Document::Data::get_value('loaded') ) {
		refresh_label($_) for @{ Kephra::Document::Data::all_nr() };
		raise_tab_by_doc_nr( Kephra::Document::Data::current_nr() );
	}
}
#
# tabbar and his menu visibility
#
sub get_visibility { _config()->{visible} }
sub set_visibility { _config()->{visible} = shift }
sub switch_visibility { show( _config()->{visible} ^ 1 ) }
sub show {
	my $visible = shift;
	$visible = get_visibility() unless defined $visible;
	$visible
		? _ref()->SetTabCtrlHeight(25)
		: _ref()->SetTabCtrlHeight(0);
	set_visibility($visible);
}

sub switch_contextmenu_visibility { 
	_config()->{contextmenu_use} ^= 1;
	Kephra::App::ContextMenu::connect_tabbar();
}
sub get_contextmenu_visibility { _config()->{contextmenu_use} }

1;