/*
 * Copyright (C) 2007-2008, 2014-2015 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#include "config.h"
#include "FTPDirectoryDocument.h"

#if ENABLE(FTPDIR)

#include "HTMLAnchorElement.h"
#include "HTMLBodyElement.h"
#include "HTMLDocumentParser.h"
#include "HTMLTableCellElement.h"
#include "HTMLTableElement.h"
#include "LocalizedStrings.h"
#include "Logging.h"
#include "FTPDirectoryParser.h"
#include "Settings.h"
#include "SharedBuffer.h"
#include "Text.h"
#include <wtf/GregorianDateTime.h>
#include <wtf/IsoMallocInlines.h>
#include <wtf/StdLibExtras.h>
#include <wtf/text/StringConcatenateNumbers.h>
#include <wtf/unicode/CharacterNames.h>

namespace WebCore {

WTF_MAKE_ISO_ALLOCATED_IMPL(FTPDirectoryDocument);

using namespace HTMLNames;
    
class FTPDirectoryDocumentParser final : public HTMLDocumentParser {
public:
    static Ref<FTPDirectoryDocumentParser> create(HTMLDocument& document)
    {
        return adoptRef(*new FTPDirectoryDocumentParser(document));
    }

private:
    void append(RefPtr<StringImpl>&&) override;
    void finish() override;

    // FIXME: Why do we need this?
    bool isWaitingForScripts() const override { return false; }

    void checkBuffer(int len = 10)
    {
        if ((m_dest - m_buffer) > m_size - len) {
            // Enlarge buffer
            int newSize = std::max(m_size * 2, m_size + len);
            int oldOffset = m_dest - m_buffer;
            m_buffer = static_cast<UChar*>(fastRealloc(m_buffer, newSize * sizeof(UChar)));
            m_dest = m_buffer + oldOffset;
            m_size = newSize;
        }
    }

    FTPDirectoryDocumentParser(HTMLDocument&);

    // The parser will attempt to load the document template specified via the preference
    // Failing that, it will fall back and create the basic document which will have a minimal
    // table for presenting the FTP directory in a useful manner
    bool loadDocumentTemplate();
    void createBasicDocument();

    void parseAndAppendOneLine(const String&);
    void appendEntry(const String& name, const String& size, const String& date, bool isDirectory);    
    Ref<Element> createTDForFilename(const String&);

    RefPtr<HTMLTableElement> m_tableElement;

    bool m_skipLF { false };
    
    int m_size { 254 };
    UChar* m_buffer;
    UChar* m_dest;
    String m_carryOver;
    
    ListState m_listState;
};

FTPDirectoryDocumentParser::FTPDirectoryDocumentParser(HTMLDocument& document)
    : HTMLDocumentParser(document)
    , m_buffer(static_cast<UChar*>(fastMalloc(sizeof(UChar) * m_size)))
    , m_dest(m_buffer)
{
}

void FTPDirectoryDocumentParser::appendEntry(const String& filename, const String& size, const String& date, bool isDirectory)
{
    auto& document = *this->document();

    auto rowElement = m_tableElement->insertRow(-1).releaseReturnValue();
    rowElement->setAttributeWithoutSynchronization(HTMLNames::classAttr, AtomString("ftpDirectoryEntryRow", AtomString::ConstructFromLiteral));

    auto typeElement = HTMLTableCellElement::create(tdTag, document);
    typeElement->appendChild(Text::create(document, String(&noBreakSpace, 1)));
    if (isDirectory)
        typeElement->setAttributeWithoutSynchronization(HTMLNames::classAttr, AtomString("ftpDirectoryIcon ftpDirectoryTypeDirectory", AtomString::ConstructFromLiteral));
    else
        typeElement->setAttributeWithoutSynchronization(HTMLNames::classAttr, AtomString("ftpDirectoryIcon ftpDirectoryTypeFile", AtomString::ConstructFromLiteral));
    rowElement->appendChild(typeElement);

    auto nameElement = createTDForFilename(filename);
    nameElement->setAttributeWithoutSynchronization(HTMLNames::classAttr, AtomString("ftpDirectoryFileName", AtomString::ConstructFromLiteral));
    rowElement->appendChild(nameElement);

    auto dateElement = HTMLTableCellElement::create(tdTag, document);
    dateElement->appendChild(Text::create(document, date));
    dateElement->setAttributeWithoutSynchronization(HTMLNames::classAttr, AtomString("ftpDirectoryFileDate", AtomString::ConstructFromLiteral));
    rowElement->appendChild(dateElement);

    auto sizeElement = HTMLTableCellElement::create(tdTag, document);
    sizeElement->appendChild(Text::create(document, size));
    sizeElement->setAttributeWithoutSynchronization(HTMLNames::classAttr, AtomString("ftpDirectoryFileSize", AtomString::ConstructFromLiteral));
    rowElement->appendChild(sizeElement);
}

Ref<Element> FTPDirectoryDocumentParser::createTDForFilename(const String& filename)
{
    auto& document = *this->document();

    String fullURL = document.baseURL().string();
    if (fullURL.endsWith('/'))
        fullURL = fullURL + filename;
    else
        fullURL = fullURL + '/' + filename;

    auto anchorElement = HTMLAnchorElement::create(document);
    anchorElement->setAttributeWithoutSynchronization(HTMLNames::hrefAttr, fullURL);
    anchorElement->appendChild(Text::create(document, filename));

    auto tdElement = HTMLTableCellElement::create(tdTag, document);
    tdElement->appendChild(anchorElement);

    return WTFMove(tdElement);
}

static String processFilesizeString(const String& size, bool isDirectory)
{
    if (isDirectory)
        return "--"_s;

    bool valid;
    int64_t bytes = size.toUInt64(&valid);
    if (!valid)
        return unknownFileSizeText();

    if (bytes < 1000000)
        return makeString(FormattedNumber::fixedWidth(bytes / 1000., 2), " KB");

    if (bytes < 1000000000)
        return makeString(FormattedNumber::fixedWidth(bytes / 1000000., 2), " MB");

    return makeString(FormattedNumber::fixedWidth(bytes / 1000000000., 2), " GB");
}

static bool wasLastDayOfMonth(int year, int month, int day)
{
    static const int lastDays[] = { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    if (month < 0 || month > 11)
        return false;

    if (month == 2) {
        if (year % 4 == 0 && (year % 100 || year % 400 == 0)) {
            if (day == 29)
                return true;
            return false;
        }

        if (day == 28)
            return true;
        return false;
    }

    return lastDays[month] == day;
}

static String processFileDateString(const FTPTime& fileTime)
{
    // FIXME: Need to localize this string?

    String timeOfDay;

    if (!(fileTime.tm_hour == 0 && fileTime.tm_min == 0 && fileTime.tm_sec == 0)) {
        int hour = fileTime.tm_hour;
        ASSERT(hour >= 0 && hour < 24);

        if (hour < 12) {
            if (hour == 0)
                hour = 12;
            timeOfDay = makeString(", ", hour, ':', pad('0', 2, fileTime.tm_min), " AM");
        } else {
            hour = hour - 12;
            if (hour == 0)
                hour = 12;
            timeOfDay = makeString(", ", hour, ':', pad('0', 2, fileTime.tm_min), " PM");
        }
    }

    // If it was today or yesterday, lets just do that - but we have to compare to the current time
    GregorianDateTime now;
    now.setToCurrentLocalTime();

    if (fileTime.tm_year == now.year()) {
        if (fileTime.tm_mon == now.month()) {
            if (fileTime.tm_mday == now.monthDay())
                return "Today" + timeOfDay;
            if (fileTime.tm_mday == now.monthDay() - 1)
                return "Yesterday" + timeOfDay;
        }
        
        if (now.monthDay() == 1 && (now.month() == fileTime.tm_mon + 1 || (now.month() == 0 && fileTime.tm_mon == 11)) &&
            wasLastDayOfMonth(fileTime.tm_year, fileTime.tm_mon, fileTime.tm_mday))
                return "Yesterday" + timeOfDay;
    }

    if (fileTime.tm_year == now.year() - 1 && fileTime.tm_mon == 12 && fileTime.tm_mday == 31 && now.month() == 1 && now.monthDay() == 1)
        return "Yesterday" + timeOfDay;

    static const char* months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "???" };

    int month = fileTime.tm_mon;
    if (month < 0 || month > 11)
        month = 12;

    String dateString;

    if (fileTime.tm_year > -1)
        dateString = makeString(months[month], ' ', fileTime.tm_mday, ", ", fileTime.tm_year);
    else
        dateString = makeString(months[month], ' ', fileTime.tm_mday, ", ", now.year());

    return dateString + timeOfDay;
}

void FTPDirectoryDocumentParser::parseAndAppendOneLine(const String& inputLine)
{
    ListResult result;
    CString latin1Input = inputLine.latin1();

    FTPEntryType typeResult = parseOneFTPLine(latin1Input.data(), m_listState, result);

    // FTPMiscEntry is a comment or usage statistic which we don't care about, and junk is invalid data - bail in these 2 cases
    if (typeResult == FTPMiscEntry || typeResult == FTPJunkEntry)
        return;

    String filename(result.filename, result.filenameLength);
    if (result.type == FTPDirectoryEntry) {
        filename.append('/');

        // We have no interest in linking to "current directory"
        if (filename == "./")
            return;
    }

    LOG(FTP, "Appending entry - %s, %s", filename.ascii().data(), result.fileSize.ascii().data());

    appendEntry(filename, processFilesizeString(result.fileSize, result.type == FTPDirectoryEntry), processFileDateString(result.modifiedTime), result.type == FTPDirectoryEntry);
}

static inline RefPtr<SharedBuffer> createTemplateDocumentData(const Settings& settings)
{
    auto buffer = SharedBuffer::createWithContentsOfFile(settings.ftpDirectoryTemplatePath());
    if (buffer)
        LOG(FTP, "Loaded FTPDirectoryTemplate of length %zu\n", buffer->size());
    return buffer;
}
    
bool FTPDirectoryDocumentParser::loadDocumentTemplate()
{
    static SharedBuffer* templateDocumentData = createTemplateDocumentData(document()->settings()).leakRef();
    // FIXME: Instead of storing the data, it would be more efficient if we could parse the template data into the
    // template Document once, store that document, then "copy" it whenever we get an FTP directory listing.
    
    if (!templateDocumentData) {
        LOG_ERROR("Could not load templateData");
        return false;
    }

    HTMLDocumentParser::insert(String(templateDocumentData->data(), templateDocumentData->size()));

    auto& document = *this->document();

    auto foundElement = makeRefPtr(document.getElementById(String("ftpDirectoryTable"_s)));
    if (!foundElement)
        LOG_ERROR("Unable to find element by id \"ftpDirectoryTable\" in the template document.");
    else if (!is<HTMLTableElement>(foundElement))
        LOG_ERROR("Element of id \"ftpDirectoryTable\" is not a table element");
    else {
        m_tableElement = downcast<HTMLTableElement>(foundElement.get());
        return true;
    }

    m_tableElement = HTMLTableElement::create(document);
    m_tableElement->setAttributeWithoutSynchronization(HTMLNames::idAttr, AtomString("ftpDirectoryTable", AtomString::ConstructFromLiteral));

    // If we didn't find the table element, lets try to append our own to the body.
    // If that fails for some reason, cram it on the end of the document as a last ditch effort.
    if (auto body = makeRefPtr(document.bodyOrFrameset()))
        body->appendChild(*m_tableElement);
    else
        document.appendChild(*m_tableElement);

    return true;
}

void FTPDirectoryDocumentParser::createBasicDocument()
{
    LOG(FTP, "Creating a basic FTP document structure as no template was loaded");

    auto& document = *this->document();

    auto bodyElement = HTMLBodyElement::create(document);
    document.appendChild(bodyElement);

    m_tableElement = HTMLTableElement::create(document);
    m_tableElement->setAttributeWithoutSynchronization(HTMLNames::idAttr, AtomString("ftpDirectoryTable", AtomString::ConstructFromLiteral));
    m_tableElement->setAttribute(HTMLNames::styleAttr, AtomString("width:100%", AtomString::ConstructFromLiteral));

    bodyElement->appendChild(*m_tableElement);

    document.processViewport("width=device-width", ViewportArguments::ViewportMeta);
}

void FTPDirectoryDocumentParser::append(RefPtr<StringImpl>&& inputSource)
{
    // Make sure we have the table element to append to by loading the template set in the pref, or
    // creating a very basic document with the appropriate table
    if (!m_tableElement) {
        if (!loadDocumentTemplate())
            createBasicDocument();
        ASSERT(m_tableElement);
    }

    bool foundNewLine = false;

    m_dest = m_buffer;
    SegmentedString string { String { WTFMove(inputSource) } };
    while (!string.isEmpty()) {
        UChar c = string.currentCharacter();

        if (c == '\r') {
            *m_dest++ = '\n';
            foundNewLine = true;
            // possibly skip an LF in the case of an CRLF sequence
            m_skipLF = true;
        } else if (c == '\n') {
            if (!m_skipLF)
                *m_dest++ = c;
            else
                m_skipLF = false;
        } else {
            *m_dest++ = c;
            m_skipLF = false;
        }

        string.advance();

        // Maybe enlarge the buffer
        checkBuffer();
    }

    if (!foundNewLine) {
        m_dest = m_buffer;
        return;
    }

    UChar* start = m_buffer;
    UChar* cursor = start;

    while (cursor < m_dest) {
        if (*cursor == '\n') {
            m_carryOver.append(String(start, cursor - start));
            LOG(FTP, "%s", m_carryOver.ascii().data());
            parseAndAppendOneLine(m_carryOver);
            m_carryOver = String();

            start = ++cursor;
        } else 
            cursor++;
    }

    // Copy the partial line we have left to the carryover buffer
    if (cursor - start > 1)
        m_carryOver.append(String(start, cursor - start - 1));
}

void FTPDirectoryDocumentParser::finish()
{
    // Possible the last line in the listing had no newline, so try to parse it now
    if (!m_carryOver.isEmpty()) {
        parseAndAppendOneLine(m_carryOver);
        m_carryOver = String();
    }

    m_tableElement = nullptr;
    fastFree(m_buffer);

    HTMLDocumentParser::finish();
}

FTPDirectoryDocument::FTPDirectoryDocument(Frame* frame, const URL& url)
    : HTMLDocument(frame, url)
{
#if !LOG_DISABLED
    LogFTP.state = WTFLogChannelState::On;
#endif
}

Ref<DocumentParser> FTPDirectoryDocument::createParser()
{
    return FTPDirectoryDocumentParser::create(*this);
}

}

#endif // ENABLE(FTPDIR)
