#include <QtWidgets>
#include "Utilities.h"
#include "MdiChild.h"
#include "ui_ExtensibleObjectModelUI.h"


/*!
 * \brief MdiChild::MdiChild
 *
 * Implementation Status: ?
 *
 */
MdiChild::MdiChild()
{
    setAttribute(Qt::WA_DeleteOnClose);
    isUntitled = true;
    connect(document(), SIGNAL(contentsChanged()), this, SIGNAL(documentContentsChanged()));
}

/*!
 * \brief MdiChild::~MdiChild
 *
 * Implementation Status: ?
 *
 */
MdiChild::~MdiChild()
{
    closing();
}

/*!
 * \brief MdiChild::newFile
 *
 * Implementation Status: ?
 *
 */
void MdiChild::newFile()
{
    static int sequenceNumber = 1;
    isUntitled = true;
    curFile = tr("document%1.txt").arg(sequenceNumber++);
    setWindowTitle(curFile + "[*]");
    connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified()));
}

/*!
 * \brief MdiChild::loadFile
 * \param fileName
 * \return
 *
 * Implementation Status: ?
 *
 */
bool MdiChild::loadFile(const QString &fileName)
{
    QFile file(fileName);
    if (!file.open(QFile::ReadOnly | QFile::Text)) {
        QMessageBox::warning(this, tr("MDI"),
                 tr("Cannot read file %1:\n%2.").arg(fileName).arg(file.errorString()));
        return false;
    }
    QTextStream in(&file);
    QApplication::setOverrideCursor(Qt::WaitCursor);
    setPlainText(in.readAll());
    QApplication::restoreOverrideCursor();

    setCurrentFile(fileName);
    connect(document(), SIGNAL(contentsChanged()), this, SLOT(documentWasModified()));
    return true;
}

/*!
 * \brief MdiChild::save
 * \return
 *
 * Implementation Status: ?
 *
 */
bool MdiChild::save()
{
    return (isUntitled) ? saveAs() : saveFile(curFile);
}

/*!
 * \brief MdiChild::saveAs prompts for the file name to save the file as
 * \return
 *
 * Implementation Status: ?
 *
 */
bool MdiChild::saveAs()
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), curFile);
    if (fileName.isEmpty())
        return false;
    return saveFile(fileName);
}

/*!
 * \brief MdiChild::saveFile
 * \param fileName
 * \return
 *
 * Implementation Status: ?
 *
 */
bool MdiChild::saveFile(const QString &fileName)
{
    QFile file(fileName);
    if (!file.open(QFile::WriteOnly | QFile::Text)) {
        QMessageBox::warning(this, tr("MDI"),
              tr("Cannot write file %1:\n%2.").arg(fileName).arg(file.errorString()));
        return false;
    }
    QTextStream out(&file);
    QApplication::setOverrideCursor(Qt::WaitCursor);
    out << toPlainText();
    QApplication::restoreOverrideCursor();

    setCurrentFile(fileName);
    return true;
}

/*!
 * \brief MdiChild::userFriendlyCurrentFile
 * \return
 *
 * Implementation Status: ?
 *
 */
QString MdiChild::userFriendlyCurrentFile()
{
    return strippedName(curFile);
}

/*!
 * \brief MdiChild::closeEvent
 * \param event
 *
 * Implementation Status: ?
 *
 */
void MdiChild::closeEvent(QCloseEvent *event)
{
    if (maybeSave()) {
        event->accept();
    } else {
        event->ignore();
    }
}

/*!
 * \brief MdiChild::documentWasModified
 *
 * Implementation Status: ?
 *
 */
void MdiChild::documentWasModified()
{
    setWindowModified(document()->isModified());
}

/*!
 * \brief MdiChild::maybeSave
 * \return
 *
 * Implementation Status: ?
 *
 */
bool MdiChild::maybeSave()
{
    if (document()->isModified()) {
        QMessageBox::StandardButton ret;
        ret = QMessageBox::warning(this, tr("MDI"),
                     tr("'%1' has been modified.\n"
                        "Do you want to save your changes?")
                     .arg(userFriendlyCurrentFile()),
                     QMessageBox::Save | QMessageBox::Discard
                     | QMessageBox::Cancel);
        if (ret == QMessageBox::Save)
            return save();
        else if (ret == QMessageBox::Cancel)
            return false;
    }
    return true;
}

/*!
 * \brief MdiChild::setCurrentFile
 * \param fileName
 *
 * Implementation Status: ?
 *
 */
void MdiChild::setCurrentFile(const QString &fileName)
{
    curFile = QFileInfo(fileName).canonicalFilePath();
    isUntitled = false;
    document()->setModified(false);
    setWindowModified(false);
    setWindowTitle(userFriendlyCurrentFile() + "[*]");
}

/*!
 * \brief MdiChild::strippedName
 * \param fullFileName
 * \return
 *
 * Implementation Status: ?
 *
 */
QString MdiChild::strippedName(const QString &fullFileName)
{
    return QFileInfo(fullFileName).fileName();
}

/*!
 * \brief MdiChild::markdownSelection
 * \param preText
 * \param postText
 *
 * Implementation Status: ?
 *
 */
void MdiChild::markdownSelection(const char* preText, const char* postText)
{
    QTextCursor cur = textCursor();
    cur.beginEditBlock();
    QString selectedText = cur.selection().toPlainText();
    cur.removeSelectedText();
    cur.insertText(preText + selectedText + postText);
    cur.endEditBlock();
}

/*!
 * \brief MdiChild::insertText
 * \param text
 *
 * Implementation Status: ?
 * TODO: Appears to replace current selection. Is that expected? Perhaps should only add text.
 *
 */
void MdiChild::insertText(const char* text)
{
    QTextCursor cur = textCursor();
    cur.beginEditBlock();
    cur.insertText(text);
    cur.endEditBlock();
}

/*!
 * \brief MdiChild::bold
 *
 * Implementation Status: 50%
 * TODO: modal bold? If no selection, click it, type, then click it again to turn off bold mode
 *
 */
void MdiChild::bold()
{
    markdownSelection("**", "**");
}

/*!
 * \brief MdiChild::italic
 *
 * Implementation Status: ?
 *
 */
void MdiChild::italic()
{
    markdownSelection("*", "*");
}

/*!
 * \brief MdiChild::quote
 *
 * Implementation Status: ?
 *
 */
void MdiChild::quote()
{
    markdownSelection("`", "`");
}

/*!
 * \brief MdiChild::code
 *
 * Implementation Status: ?
 *
 */
void MdiChild::code()
{
    //markdownSelection("*", "*");
    // Need to add indentation of text with 4 spaces each line
}

/*!
 * \brief MdiChild::heading1
 *
 * Implementation Status: ?
 *
 */
void MdiChild::heading1()
{
    markdownSelection("# ", " #");
}

/*!
 * \brief MdiChild::heading2
 *
 * Implementation Status: ?
 *
 */
void MdiChild::heading2()
{
    markdownSelection("## ", " ##");
}

/*!
 * \brief MdiChild::heading3
 *
 * Implementation Status: ?
 *
 */
void MdiChild::heading3()
{
    markdownSelection("### ", " ###");
}

/*!
 * \brief MdiChild::heading4
 *
 * Implementation Status: ?
 *
 */
void MdiChild::heading4()
{
    markdownSelection("#### ", " ####");
}

/*!
 * \brief MdiChild::hyperlink
 *
 * Implementation Status: ?
 *
 */
void MdiChild::hyperlink()
{
}

/*!
 * \brief MdiChild::image
 *
 * Implementation Status: ?
 *
 */
void MdiChild::image()
{
}

/*!
 * \brief MdiChild::unorderedList
 *
 * Implementation Status: ?
 *
 */
void MdiChild::unorderedList()
{
}

/*!
 * \brief MdiChild::orderedList
 *
 * Implementation Status: ?
 *
 */
void MdiChild::orderedList()
{
}

/*!
 * \brief MdiChild::horizontalRule
 *
 * Implementation Status: 0%
 *
 */
void MdiChild::horizontalRule()
{
    insertText("----------");
}

/*!
 * \brief MdiChild::timestamp
 *
 * Implementation Status: 0%
 * TODO: Appears to replace current selection. Is that expected?
 *
 */
void MdiChild::timestamp()
{
    insertText("[TIMESTAMP]");
}

/*!
 * \brief MdiChild::pageNumber
 *
 * Implementation Status: 0%
 *
 */
void MdiChild::pageNumber()
{
    insertText("[PAGENUM]");
}

/*!
 * \brief MdiChild::pageCount
 *
 * Implementation Status: 0%
 *
 */
void MdiChild::pageCount()
{
    insertText("[PAGECOUNT]");
}

/*!
 * \brief MdiChild::del
 *
 * Implementation Status: 100%
 *
 */
void MdiChild::del()
{
    QTextCursor cur = textCursor();
    cur.beginEditBlock();
    cur.removeSelectedText();
    cur.endEditBlock();
}

/*!
 * \brief MdiChild::undo
 *
 * Implementation Status: 100%
 *
 */
void MdiChild::undo()
{
    QTextEdit::undo();
}

/*!
 * \brief MdiChild::redo
 *
 * Implementation Status: 100%
 *
 */
void MdiChild::redo()
{
    QTextEdit::redo();
}

/*!
 * \brief MdiChild::find
 *
 * Implementation Status: 0%
 *
 */
void MdiChild::find()
{
}

/*!
 * \brief MdiChild::findNext
 *
 * Implementation Status: 0%
 *
 */
void MdiChild::findNext()
{
}

/*!
 * \brief MdiChild::findPrevious
 *
 * Implementation Status: 0%
 *
 */
void MdiChild::findPrevious()
{
}

/*!
 * \brief MdiChild::goToLine
 *
 * Implementation Status: 0%
 *
 */
void MdiChild::goToLine()
{
}

