/***************************************************************************
 *   Copyright (C) 2003-2005 by Michael Goettsche                          *
 *   mail@tuxipuxi.org                                                     *
 *                                                                         *
 *   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.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/


#include <tdeconfig.h>
#include <tdeglobal.h>
#include <kled.h>
#include <tdefiledialog.h>
#include <tdeaboutapplication.h>

#include <tdeapplication.h>
#include <tqpushbutton.h>
#include <tqlistview.h>
#include <tqlineedit.h>
#include <tqdir.h>
#include <tqstring.h>
#include <tqstringlist.h>
#include <tqbuttongroup.h>
#include <tqcheckbox.h>
#include <tqprocess.h>
#include <tqtextedit.h>
#include <tqframe.h>
#include <tqtimer.h>
#include <tdemessagebox.h>
#include <kstandarddirs.h>
#include <tdeversion.h>
#include <tqpopupmenu.h>

#include "kstreamripper.h"
#include "streampropertiesdlg.h"
#include "processlistviewitem.h"
#include "processcontroller.h"



KStreamRipper::KStreamRipper( TQWidget* parent, const char* name )
    : KStreamRipperBase( parent,name )
	, m_browser("_shoutcast._tcp",0,true)
{
    m_destEdit->setText( TQDir::homeDirPath() );

    m_streamsListView->addColumn( "Name" );
    m_streamsListView->addColumn( "Status" );
    m_streamsListView->addColumn( "Size" );

    // Create context menu
    contextMenu = new TQPopupMenu( m_streamsListView );
    contextMenu->insertItem( i18n("&Add Stream"), this, TQ_SLOT(addStreamButtonClicked()), CTRL+Key_A );
    contextMenu->insertItem( i18n("&Edit Stream"), this, TQ_SLOT(editStreamButtonClicked()), CTRL+Key_E );
    contextMenu->insertItem( i18n("&Delete Stream"), this, TQ_SLOT(deleteStreamButtonClicked()), Key_Delete );
    contextMenu->insertSeparator();
    contextMenu->insertItem( i18n("&Rip Stream"), this, TQ_SLOT(ripButtonClicked()), CTRL+Key_R, 2 );
    contextMenu->insertItem( i18n("&Stop Rip"), this, TQ_SLOT(stopRipButtonClicked()), CTRL+Key_S, 3 );
    contextMenu->insertItem( i18n("&Tune in"), this, TQ_SLOT(tuneInButtonClicked()), CTRL+Key_T );

    //app config
    TDEConfig *appConfig = TDEGlobal::config();

    m_destEdit->setText( appConfig->readEntry( "Destination" , "" ) );
    m_timeEdit->setText( appConfig->readEntry( "Riptime", "0" ));
    m_tuneInEdit->setText( appConfig->readEntry( "Command", "xmms <url>" ));
    m_id3Checkbox->setChecked( appConfig->readBoolEntry( "Id3Tag", 1 ));
    m_unicodeCheckbox->setChecked( appConfig->readBoolEntry( "Unicode", 1 ));

    //listview entrys
    TQStringList nameList,urlList,descList;

    nameList = appConfig->readListEntry( "names" );
    urlList = appConfig->readListEntry( "urls"  );
    descList = appConfig->readListEntry( "descs" );
    size_t numEntries = nameList.size();
    if (urlList.size() < numEntries)
    {
      numEntries = urlList.size();
    }
    for(size_t idx = 0; idx < numEntries; ++idx)
    {
        ProcessListViewItem * procItem = new ProcessListViewItem( m_streamsListView, nameList[idx], "", "");
        procItem->setRenameEnabled(0, true);
        ProcessController *pc = procItem->getProcessController();
        pc->setUrl( urlList[idx] );
        if (idx < descList.size())
        {
          pc->setDescription( descList[idx] );
        }
        connect(pc, TQ_SIGNAL(stopRipSignal(ProcessController*)), this, TQ_SLOT(ripStopped(ProcessController*)));
    }

    //CONNECTS

    //clicks
    connect(m_addStreamButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(addStreamButtonClicked()));
    connect(m_editStreamButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(editStreamButtonClicked()));
    connect(m_deleteStreamButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(deleteStreamButtonClicked()));
    connect(m_tuneInButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(tuneInButtonClicked()));
    connect(m_ripButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(ripButtonClicked()));
    connect(m_stopRipButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(stopRipButtonClicked()));
    connect(m_browseButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(browseButtonClicked()));
    connect(m_helpButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(helpButtonClicked()));
    connect(m_aboutButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(aboutButtonClicked()));
    connect(m_quitButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(quitButtonClicked()));
    connect(m_streamsListView, TQ_SIGNAL( contextMenuRequested( TQListViewItem *, const TQPoint& , int ) ),
            this, TQ_SLOT( slotContextMenu( TQListViewItem *, const TQPoint &, int ) ) );

    //other
    connect( m_streamsListView, TQ_SIGNAL(selectionChanged()), this, TQ_SLOT( selectedNewListItem()) );

    // zeroconf
    connect(&m_browser, TQ_SIGNAL(serviceAdded(DNSSD::RemoteService::Ptr)), this,
            TQ_SLOT(serviceAdded(DNSSD::RemoteService::Ptr)));
    connect(&m_browser, TQ_SIGNAL(serviceRemoved(DNSSD::RemoteService::Ptr)), this,
            TQ_SLOT(serviceRemoved(DNSSD::RemoteService::Ptr)));
    m_browser.startBrowse();
}


KStreamRipper::~KStreamRipper()
{
    delete contextMenu;
}


void KStreamRipper::closeEvent( TQCloseEvent *e )
{
    TDEConfig *appConfig = TDEGlobal::config();

    appConfig->writeEntry( "Destination", m_destEdit->text());
    appConfig->writeEntry( "Riptime", m_timeEdit->text());
    appConfig->writeEntry( "Command", m_tuneInEdit->text());
    appConfig->writeEntry( "Id3Tag", m_id3Checkbox->isChecked());
    appConfig->writeEntry( "Unicode", m_unicodeCheckbox->isChecked());

    //save the listview entrys
    TQStringList nameList,urlList,descList;
    while( m_streamsListView->childCount() > 0)
    {
        ProcessListViewItem * procItem = (ProcessListViewItem*)m_streamsListView->firstChild();
        if (!procItem->getProcessController()->getAutomatic())
        {
            nameList.append( procItem->text( 0 ));
            urlList.append( procItem->getProcessController()->getUrl() );
            descList.append( procItem->getProcessController()->getDescription() );
            if ( procItem->getProcessController()->getStatus() )
            {
                procItem->getProcessController()->stopRip();
            }
        }
        delete procItem;
    }

    appConfig->writeEntry( "names", nameList );
    appConfig->writeEntry( "urls" , urlList  );
    appConfig->writeEntry( "descs", descList );

    appConfig->sync();

    e->accept();
}


//SLOTS
void KStreamRipper::addStreamButtonClicked()
{
    StreamPropertiesDlg *dlg = new StreamPropertiesDlg(this);
    connect( dlg, TQ_SIGNAL( finished( StreamPropertiesDlg* )), this, TQ_SLOT( addStreamFinished( StreamPropertiesDlg* )) );
    dlg->setCaption("Add Stream...");
    dlg->show();
}

void KStreamRipper::editStreamButtonClicked()
{
    ProcessListViewItem *ProcItem = (ProcessListViewItem*)m_streamsListView->currentItem();
    StreamPropertiesDlg *dlg = new StreamPropertiesDlg(this);
    connect( dlg, TQ_SIGNAL( finished( StreamPropertiesDlg* )), this, TQ_SLOT( editStreamFinished( StreamPropertiesDlg* )) );
    dlg->setCaption("Edit Stream");
    dlg->d_nameEdit->setText(ProcItem->text(0));
    dlg->d_urlEdit->setText(ProcItem->getProcessController()->getUrl());
    dlg->d_descEdit->setText(ProcItem->getProcessController()->getDescription());
    dlg->show();

}

void KStreamRipper::deleteStreamButtonClicked()
{
    ProcessListViewItem *procItem = (ProcessListViewItem*)m_streamsListView->currentItem();
    if (procItem)
    {
        int res = KMessageBox::questionYesNo(this, i18n("Delete the stream '%1'?").arg(procItem->text(0)),
                i18n("Delete stream"));
        if (res == KMessageBox::Yes)
        {
            stopRipButtonClicked();
            delete procItem;
        }
    }
}

void KStreamRipper::slotContextMenu( TQListViewItem* Item, const TQPoint & point, int)
{
    if( Item ) {
         contextMenu->popup( point );
    }
}

void KStreamRipper::tuneInButtonClicked()
{
    if( m_streamsListView->currentItem() )
	{
            TQString command = m_tuneInEdit->text().replace( "<url>",  m_UrlEdit->text() );

            TQStringList commands = TQStringList::split( " ", command );

            TQProcess *process = new TQProcess( this );
            process->setArguments( commands );

            process->start();
	}
    else ;
}

void KStreamRipper::serviceAdded(DNSSD::RemoteService::Ptr srv)
{
    ProcessListViewItem * proc = new ProcessListViewItem( m_streamsListView, srv->serviceName(), "", "");
    proc->getProcessController()->setUrl( TQString("http://%1:%2%3").arg(srv->hostName()).arg(srv->port()).arg(srv->textData()["path"]) );
    proc->getProcessController()->setDescription( i18n("found by Zeroconf") );
    proc->getProcessController()->setAutomatic(true);
    proc->getProcessController()->setService(srv);

}
void KStreamRipper::serviceRemoved(DNSSD::RemoteService::Ptr srv)
{
    TQListViewItemIterator iter( m_streamsListView );

    while( iter.current() ) {
            ProcessListViewItem * ProcItem = (ProcessListViewItem*)iter.current();
	    if (ProcItem->getProcessController()->getAutomatic() &&
                srv==ProcItem->getProcessController()->getService()) {
				delete ProcItem;
				return;
				}
	    ++iter;
    }

}

void KStreamRipper::ripButtonClicked()
{
    if (!(TDEStandardDirs::findExe("streamripper").isEmpty())) {
        ProcessListViewItem * ProcItem = (ProcessListViewItem*)m_streamsListView->currentItem();
        ProcItem->getProcessController()->startRip(m_destEdit->text(), m_timeEdit->text(),
                m_unicodeCheckbox->isChecked());
        m_ripButton->setEnabled( false );
        contextMenu->setItemEnabled(2, false);
        contextMenu->setItemEnabled(3, true);
        m_stopRipButton->setEnabled( true );
    } else {
        KMessageBox::error(this, "The streamripper executable wasn't found. Make sure "
                           "it's in your path.", "streamripper not found");
    }
}

void KStreamRipper::ripStopped(ProcessController *curProc)
{
    const ProcessController *proc = ((ProcessListViewItem*)m_streamsListView->currentItem())->getProcessController();
    if (curProc == proc)
    {
        m_ripButton->setEnabled( true );
        contextMenu->setItemEnabled(2, true);
        contextMenu->setItemEnabled(3, false);
        m_stopRipButton->setEnabled( false );
    }
}

void KStreamRipper::stopRipButtonClicked()
{
    ProcessListViewItem * ProcItem = (ProcessListViewItem*)m_streamsListView->currentItem();
    ProcItem->getProcessController()->stopRip();
    m_ripButton->setEnabled( true );
    m_stopRipButton->setEnabled( false );
}

void KStreamRipper::browseButtonClicked()
{
    TQString openDest = KFileDialog::getExistingDirectory( TQDir::homeDirPath(),
                                                          this,
                                                          "Select Destination..." );
    if ( !openDest.isEmpty() )
        m_destEdit->setText( openDest );
}

void KStreamRipper::helpButtonClicked()
{
    kapp->invokeHelp( TQString(), "kstreamripper" );
}

void KStreamRipper::aboutButtonClicked()
{
    TDEAboutApplication *aboutApp = new TDEAboutApplication();
    aboutApp->show();
}

void KStreamRipper::quitButtonClicked()
{
    this->close();
}

void KStreamRipper::selectedNewListItem()
{
    if ( !m_streamsListView->selectedItem() ) {
        m_editStreamButton->setEnabled( false );
        m_deleteStreamButton->setEnabled( false );
        m_tuneInButton->setEnabled( false );
        m_ripButton->setEnabled( false );
        m_DescriptionEdit->setText( TQString() );
        m_DescriptionEdit->setEnabled(false);
        m_UrlEdit->setEnabled(false);
        m_UrlEdit->setText( TQString() );
        return;
    }
    ProcessController * ProcCtl = ((ProcessListViewItem*)m_streamsListView->currentItem())->getProcessController();

    // reconfigure what the user is allowed to do based on if this process is ripping
    m_ripButton->setEnabled( !ProcCtl->getStatus() );
    contextMenu->setItemEnabled(2, !ProcCtl->getStatus() );
    m_stopRipButton->setEnabled( ProcCtl->getStatus() );
    contextMenu->setItemEnabled(3, ProcCtl->getStatus() );
    m_tuneInButton->setEnabled( true );
    m_editStreamButton->setEnabled( !ProcCtl->getAutomatic() );
    m_deleteStreamButton->setEnabled( !ProcCtl->getAutomatic() );

    m_DescriptionEdit->setText(ProcCtl->getDescription());
    m_DescriptionEdit->setEnabled(true);
    m_UrlEdit->setText(ProcCtl->getUrl());
    m_UrlEdit->setEnabled( !ProcCtl->getAutomatic() );
}

void KStreamRipper::addStreamFinished( StreamPropertiesDlg *e )
{
    ProcessListViewItem *procItem = new ProcessListViewItem( m_streamsListView, e->d_nameEdit->text(), "", "");
    ProcessController *pc = procItem->getProcessController();
    pc->setUrl( e->d_urlEdit->text() );
    pc->setDescription( e->d_descEdit->text() );
    connect(pc, TQ_SIGNAL(stopRipSignal(ProcessController*)), this, TQ_SLOT(ripStopped(ProcessController*)));
}

void KStreamRipper::editStreamFinished( StreamPropertiesDlg *e )
{
    ProcessListViewItem *procItem = (ProcessListViewItem*)m_streamsListView->currentItem();
    ProcessController *pc = procItem->getProcessController();
    procItem->setText(0, e->d_nameEdit->text());
    pc->setUrl( e->d_urlEdit->text() );
    pc->setDescription( e->d_descEdit->text() );
    m_UrlEdit->setText( e->d_urlEdit->text() );
    m_DescriptionEdit->setText( e->d_descEdit->text() );
}

#include "kstreamripper.moc"
