/***************************************************************************
 *   Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com       *
 *   Please do not use email address above for bug reports; see            *
 *   the README file                                                       *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   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.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.             *
 ***************************************************************************/

// Do not use tr() or i18n() in this file - this class is not derived from TQObject.

#include <tqregexp.h>
#include <tqstring.h>
#include <tqdir.h>

#include "libchmfile.h"
#include "libchmurlfactory.h"

#include "kchmconfig.h"
#include "kchmviewwindow.h"
#include "kchmmainwindow.h"
#include "kchmviewwindowmgr.h"
#include "kchmnavtoolbar.h"


KCHMViewWindow::KCHMViewWindow( TQTabWidget * parent )
{
	invalidate();
	m_contextMenu = 0;
	m_contextMenuLink = 0;
	m_historyMaxSize = 25;
	
	m_parentTabWidget = parent;
}

KCHMViewWindow::~KCHMViewWindow()
{
}

void KCHMViewWindow::invalidate( )
{
	m_base_url = "/";
	m_openedPage = TQString();
	m_newTabLinkKeeper = TQString();

	m_historyCurrentPos = 0;
	m_history.clear();
	
	updateNavigationToolbar();
}



TQString KCHMViewWindow::makeURLabsolute ( const TQString & url, bool set_as_base )
{
	TQString p1, p2, newurl = url;

	if ( !LCHMUrlFactory::isRemoteURL (url, p1)
	&& !LCHMUrlFactory::isJavascriptURL (url)
	&& !LCHMUrlFactory::isNewChmURL (url, p1, p2) )
	{
		newurl = TQDir::cleanDirPath (url);

		// Normalize url, so it becomes absolute
		if ( newurl[0] != '/' )
			newurl = m_base_url + "/" + newurl;
	
		newurl = TQDir::cleanDirPath (newurl);

		if ( set_as_base )
		{
			m_base_url = newurl;
		
			// and set up new baseurl
			int i = newurl.findRev('/');
			if ( i != -1 )
				m_base_url = TQDir::cleanDirPath (newurl.left (i + 1));
		}
	}

//tqDebug ("KCHMViewWindow::makeURLabsolute (%s) -> (%s)", url.ascii(), newurl.ascii());
	return newurl;
}

bool KCHMViewWindow::openUrl ( const TQString& origurl )
{
	TQString chmfile, page, newurl = origurl;

	if ( !origurl )
		return true;

	// URL could be a complete ms-its link. The file should be already loaded (for TQTextBrowser),
	// or will be loaded (for tdeio slave). We care only about the path component.
	if ( LCHMUrlFactory::isNewChmURL( newurl, chmfile, page ) )
	{
		// If a new chm file is opened here, and we do not use KCHMLPart, we better abort
		if ( chmfile != ::mainWindow->getOpenedFileName() && appConfig.m_kdeUseTQTextBrowser )
			tqFatal("KCHMViewWindow::openUrl(): opened new chm file %s while current is %s",
				   chmfile.ascii(), ::mainWindow->getOpenedFileName().ascii() );

		// It is OK to have a new file in chm for TDEHTMLPart
		newurl = page;
	}

	makeURLabsolute (newurl);
	handleStartPageAsImage( newurl );
	
	if ( openPage (newurl) )
	{
		m_newTabLinkKeeper = TQString();
		m_openedPage = newurl;
		
		mainWindow->viewWindowMgr()->setTabName( this );
		return true;
	}

	return false;
}

void KCHMViewWindow::handleStartPageAsImage( TQString & link )
{
	// Handle pics
	if ( link.endsWith( ".jpg", false )
	|| link.endsWith( ".jpeg", false )
	|| link.endsWith( ".gif", false )
	|| link.endsWith( ".png", false )
	|| link.endsWith( ".bmp", false ) )
		link += LCHMUrlFactory::getInternalUriExtension();
}


KTQPopupMenu * KCHMViewWindow::createStandardContextMenu( TQWidget * parent )
{
	KTQPopupMenu * contextMenu = new KTQPopupMenu( parent );
	
	contextMenu->insertItem ( "&Copy", ::mainWindow, TQT_SLOT(slotBrowserCopy()) );
	contextMenu->insertItem ( "&Select all", ::mainWindow, TQT_SLOT(slotBrowserSelectAll()) );
		
	return contextMenu;
}


KTQPopupMenu * KCHMViewWindow::getContextMenu( const TQString & link, TQWidget * parent )
{
	if ( link.isNull() )
	{
		// standard context menu
		if ( !m_contextMenu )
			m_contextMenu = createStandardContextMenu( parent );
		
		return m_contextMenu;
	}
	else
	{
		// Open in New Tab context menu
		// standard context menu
		if ( !m_contextMenuLink )
		{
			m_contextMenuLink = createStandardContextMenu( parent );
			m_contextMenuLink->insertSeparator();
			
			m_contextMenuLink->insertItem ( "&Open this link in a new tab", ::mainWindow, TQT_SLOT(slotOpenPageInNewTab()), TQKeySequence("Shift+Enter") );
			
			m_contextMenuLink->insertItem ( "&Open this link in a new background tab", ::mainWindow, TQT_SLOT(slotOpenPageInNewBackgroundTab()), TQKeySequence("Ctrl+Enter") );
		}
		
		setTabKeeper( link );
		return m_contextMenuLink;
	}
}

TQString KCHMViewWindow::getTitle() const
{
	TQString title = ::mainWindow->chmFile()->getTopicByUrl( m_openedPage );
	
	if ( title.isEmpty() )
		title = m_openedPage;
	
	return title;
}


void KCHMViewWindow::navigateForward()
{
	if ( m_historyCurrentPos < m_history.size() )
	{
		m_historyCurrentPos++;		
		::mainWindow->openPage( m_history[m_historyCurrentPos].getUrl() );
		setScrollbarPosition( m_history[m_historyCurrentPos].getScrollPosition() );
		
		// By default navigation starts with empty array, and a new entry is added when
		// you change the current page (or it may not be added). So to have the whole system
		// worked, the m_historyCurrentPos should never be m_history.size() - 1, it should be
		// either greater or lesser.
		// 
		// This is a dirty hack - but the whole navigation system now looks to me like
		// it was written by some drunk monkey - which is probably not far from The Real Truth.
		// Shame on me - Tim.
		if ( m_historyCurrentPos == (m_history.size() - 1) )
			m_historyCurrentPos++;
	}
	
	updateNavigationToolbar();
}

void KCHMViewWindow::navigateBack( )
{
	if ( m_historyCurrentPos > 0 )
	{
		// If we're on top of list, and pressing Back, the last page is still
		// not in list - so add it, if it is not still here
		if ( m_historyCurrentPos == m_history.size() )
		{
			if ( m_history[m_historyCurrentPos-1].getUrl() != m_openedPage )
				m_history.push_back( KCHMUrlHistory( m_openedPage, getScrollbarPosition() ) );
			else
			{
				// part 2 of the navigation hack - see navigateForward() comment
				m_history[m_historyCurrentPos-1].setScrollPosition( getScrollbarPosition() );
				m_historyCurrentPos--;
			}
		}

		m_historyCurrentPos--;
	
		::mainWindow->openPage( m_history[m_historyCurrentPos].getUrl() );
		setScrollbarPosition( m_history[m_historyCurrentPos].getScrollPosition() );
	}
	
	updateNavigationToolbar();
}

void KCHMViewWindow::navigateHome( )
{
	::mainWindow->openPage( ::mainWindow->chmFile()->homeUrl() );
}

void KCHMViewWindow::addNavigationHistory( const TQString & url, int scrollpos )
{
	// shred the 'forward' history
	if ( m_historyCurrentPos < m_history.size() )
		m_history.erase( m_history.at( m_historyCurrentPos ), m_history.end());

	// do not grow the history if already max size
	if ( m_history.size() >= m_historyMaxSize )
		m_history.pop_front();

	m_history.push_back( KCHMUrlHistory( url, scrollpos ) );
	m_historyCurrentPos = m_history.size();
			
	updateNavigationToolbar();
}

void KCHMViewWindow::updateNavigationToolbar( )
{
	// Dump navigation for debugging
#if 0
	tqDebug("\nNavigation dump (%d entries, current pos %d)", m_history.size(), m_historyCurrentPos );
	for ( unsigned int i = 0; i < m_history.size(); i++ )
		tqDebug("[%02d]: %s [%d]", i, m_history[i].getUrl().ascii(),  m_history[i].getScrollPosition());
#endif
	
	if ( mainWindow )
	{
		mainWindow->navigationToolbar()->updateIconStatus( 
					m_historyCurrentPos > 0,
					m_historyCurrentPos < (m_history.size() - 1) );
	}
}

KTQPopupMenu * KCHMViewWindow::createListItemContextMenu( TQWidget * w )
{
	KTQPopupMenu * contextMenu = new KTQPopupMenu( w );
		
	contextMenu->insertItem ( "&Open this link in a new tab",
							  ::mainWindow, 
							  TQT_SLOT( slotOpenPageInNewTab() ), 
							  TQKeySequence( "Shift+Enter" ) );
			
	contextMenu->insertItem ( "&Open this link in a new background tab", 
							  ::mainWindow, 
							  TQT_SLOT( slotOpenPageInNewBackgroundTab() ),
							  TQKeySequence( "Ctrl+Enter" ) );

	return contextMenu;
}

void KCHMViewWindow::setTabKeeper( const TQString & link )
{
	// If we clicked on relative link, make sure we convert it to absolute right now,
	// because later we will not have access to this view window variables
	m_newTabLinkKeeper = link;
	if ( m_newTabLinkKeeper[0] == '#' && !m_openedPage.isEmpty() )
	{
			// Clean up opened page URL
		int pos = m_openedPage.find ('#');
		TQString fixedpath = pos == -1 ? m_openedPage : m_openedPage.left (pos);
		m_newTabLinkKeeper = fixedpath + m_newTabLinkKeeper;
	}
		
	m_newTabLinkKeeper = makeURLabsolute( m_newTabLinkKeeper, false );
}
