/**************************************************************************
 *  Karlyriceditor - a lyrics editor and CD+G / video export for Karaoke  *
 *  songs.                                                                *
 *  Copyright (C) 2009-2013 George Yunaev, support@ulduzsoft.com          *
 *                                                                        *
 *  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 3 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, see <http://www.gnu.org/licenses/>. *
 **************************************************************************/

#ifndef EDITOR_H
#define EDITOR_H

#include <QTextEdit>
#include <QImage>
#include <QTime>
#include <QTextObjectInterface>
#include <QRegularExpression>

#include "lyrics.h"
#include "validator.h"

class Project;
class BackgroundEvents;


static inline QString markToTime( qint64 mark )
{
	int min = mark / 60000;
	int sec = (mark - min * 60000) / 1000;
	int msec = mark - (min * 60000 + sec * 1000 );

    return QString::asprintf( "%02d:%02d.%02d", min, sec, msec / 10 );
}

static inline qint64 timeToMark( QString data )
{
    QRegularExpression rxtime( "^(\\d+):(\\d+)\\.(\\d+)$");

    QRegularExpressionMatch match = rxtime.match( data );

    if ( !match.hasMatch() )
		return -1;

    return match.captured( 1 ).toInt() * 60000 + match.captured( 2 ).toInt() * 1000 + match.captured( 3 ).toInt() * 10;
}


//
// Architecturally only editor is responsible for formats, and know everything about
// any specific lyrics format. This is done here and not in Project to provide syntax
// highlighting.
//
class Editor : public QTextEdit
{
	Q_OBJECT

	public:
		static const char * PLACEHOLDER;
		static const char * PLACEHOLDER_VALUE;

		Editor( QWidget * parent );

		void	setProject( Project* proj );

		void	insertTimeTag( qint64 timing );
		void	insertImageTag( const QString& file );
		void	insertVideoTag( const QString& file );
		void	insertColorChangeTag( const QString& name );
        void	insertBackgroundColorChangeTag( const QString& name );
		void	removeLastTimeTag();
		void	addMissingTimingMarks();
		void	removeAllTimeTags();
		void	removeExtraWhitespace();
		void	adjustTimings();

		// Validate the lyrics
		bool	validate( const QFont * font = 0, const QSize * fitsize = 0 );
		void	validate( QList<ValidatorError>& errors, const QFont * font = 0, const QSize * fitsize = 0 );

		// Export/Import functions to process lyrics. This generally does not work
		// for lyrics in "editing" phase, and requires the lyrics to be validated.
		bool	exportLyrics( Lyrics * lyrics );
		void	importLyrics( const Lyrics& lyrics );

		// Export/Import functions to store/load lyrics from a project file or
		// temporary storage. Not really useful for anything else.
		QString	exportToString();
		bool	importFromString( const QString& lyricstr );
		bool	importFromOldString( const QString& lyricstr );

    signals:
        void    lyricsChanged( qint64 time );

	public slots:
		void	textModified();
		void	splitLine();
        void    followingTick( qint64 tick );

	protected:
		bool canInsertFromMimeData ( const QMimeData * source ) const;
		QMimeData * createMimeDataFromSelection () const;
		void insertFromMimeData ( const QMimeData * source );
		bool event ( QEvent * event );

	private:
		QString		validateSpecial( const QString& string );
		QTextCursor cursorAtPoint( const QPoint& point );
		qint64		timeForPosition( QTextCursor cur );

		// Ensure the cursor is in the middle of the screen if possible
		void		ensureCursorMiddle();

		void	cursorToLine( int line, int column );

		Project		 *	m_project;
		unsigned int	m_timeId; // for remove tag
};

#endif // EDITOR_H
