/*
* Copyright (C) 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,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* 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 "stdafx.h"
#include "PageLoadTestClient.h"

#include "MiniBrowser.h"
#include <WebCore/PlatformExportMacros.h>
#include <wtf/Assertions.h>
#include <wtf/FilePrintStream.h>
#include <cmath>

static const CFTimeInterval waitForNewResourceLoadDuration = 0.1;

PageLoadTestClient::PageLoadTestClient(MiniBrowser* host, bool pageLoadTesting)
    : m_host(host)
    , m_repetitions(pageLoadTesting ? 20 : 1)
    , m_waitForLoadToReallyEnd(this, &PageLoadTestClient::endPageLoad)
    , m_pageLoadTesting(pageLoadTesting)
{
}

void PageLoadTestClient::pageLoadStartedAtTime(CFAbsoluteTime startTime)
{
    m_startTimes.append(startTime);
}

void PageLoadTestClient::didStartProvisionalLoad(IWebFrame& frame)
{
    _com_ptr_t<_com_IIID<IWebFrame2, &__uuidof(IWebFrame2)>> frame2;
    if (FAILED(frame.QueryInterface(&frame2.GetInterfacePtr())))
        return;

    BOOL mainFrame = FALSE;
    if (frame2 && FAILED(frame2->isMainFrame(&mainFrame)))
        return;

    if (mainFrame) {
        clearPageLoadState();
        pageLoadStartedAtTime(CFAbsoluteTimeGetCurrent());
    }
}

void PageLoadTestClient::didCommitLoad()
{
    ++m_frames;
}

void PageLoadTestClient::didFirstLayoutForMainFrame()
{
    // Nothing to do
}

void PageLoadTestClient::didHandleOnLoadEvents()
{
    ++m_onLoadEvents;
    maybeEndPageLoadSoon();
}

void PageLoadTestClient::didFinishLoad()
{
    m_currentPageLoadFinished = true;
    maybeEndPageLoadSoon();
}

void PageLoadTestClient::didFailLoad()
{
    --m_frames;
}

void PageLoadTestClient::didInitiateResourceLoad(uint64_t resourceIdentifier)
{
    if (!resourceIdentifier) {
        WTFLogAlways("Saw resourceIdentifier=0. This must be a bug in the loader code. The results may be invalid.");
        return;
    }
    m_loadingSubresources.add(resourceIdentifier);
}

void PageLoadTestClient::didEndResourceLoad(uint64_t resourceIdentifier)
{
    if (!resourceIdentifier) {
        WTFLogAlways("Saw resourceIdentifier=0. This must be a bug in the loader code. The results may be invalid.");
        return;
    }
    auto found = m_loadingSubresources.find(resourceIdentifier);
    if (found == m_loadingSubresources.end())
        return;
    m_loadingSubresources.remove(found);
    maybeEndPageLoadSoon();
}

void PageLoadTestClient::pageLoadEndedAtTime(CFAbsoluteTime endTime)
{
    ASSERT(!m_pageLoadTesting || m_endTimes.size() == m_currentRepetition);
    m_endTimes.append(endTime);

    if (m_currentRepetition) {
        CFTimeInterval pageLoadTime = (m_endTimes[m_currentRepetition] - m_startTimes[m_currentRepetition]);
        if (pageLoadTime > m_longestTime)
            m_longestTime = pageLoadTime;

        m_totalTime += pageLoadTime;
        m_totalSquareRootsOfTime += std::sqrt(pageLoadTime);
        m_pagesTimed++;
        m_geometricMeanProductSum *= pageLoadTime;
    }

    if (m_pageLoadTesting) {
        ++m_currentRepetition;
        if (m_currentRepetition != m_repetitions)
            m_host->loadURL(m_url);
        else {
            dumpRunStatistics();
            m_host->exitProgram();
        }
    }
}

void PageLoadTestClient::endPageLoad(Timer<PageLoadTestClient>* timer)
{
    ASSERT_UNUSED(timer, timer == &m_waitForLoadToReallyEnd);

    if (!shouldConsiderPageLoadEnded())
        return;
    pageLoadEndedAtTime(m_pageLoadEndTime);
    clearPageLoadState();
}

void PageLoadTestClient::clearPageLoadState()
{
    m_currentPageLoadFinished = false;
    m_frames = 0;
    m_onLoadEvents = 0;
    m_pageLoadEndTime = 0;
    m_loadingSubresources.clear();
    m_waitForLoadToReallyEnd.invalidate();
}

bool PageLoadTestClient::shouldConsiderPageLoadEnded() const
{
    return m_currentPageLoadFinished && m_onLoadEvents == m_frames && m_loadingSubresources.isEmpty();
}

void PageLoadTestClient::maybeEndPageLoadSoon()
{
    if (!shouldConsiderPageLoadEnded())
        return;
    m_pageLoadEndTime = CFAbsoluteTimeGetCurrent();
    if (m_waitForLoadToReallyEnd.isValid())
        m_waitForLoadToReallyEnd.invalidate();
    m_waitForLoadToReallyEnd.schedule(waitForNewResourceLoadDuration, false);
}

#if OS(WINDOWS)
void PageLoadTestClient::setPageURL(const _bstr_t& pageURL)
{
    m_url = pageURL;
}
#endif

void PageLoadTestClient::dumpRunStatistics()
{
    const long maxPathLength = 1024;

    char filenameSuffix[maxPathLength + 1];

#if PLATFORM(WIN)
    DWORD pid = GetCurrentProcessId();
    _snprintf(filenameSuffix, sizeof(filenameSuffix), ".%d.txt", pid);
#else
    long pid = getpid();
    snprintf(filenameSuffix, sizeof(filenameSuffix), ".%d.txt", pid);
#endif

    const char* filename = "webkit_performance_log";
    char actualFilename[maxPathLength + 1];

#if PLATFORM(WIN)
    _snprintf(actualFilename, sizeof(actualFilename), "%s%s", filename, filenameSuffix);
#else
    snprintf(actualFilename, sizeof(actualFilename), "%s%s", filename, filenameSuffix);
#endif

    std::unique_ptr<WTF::FilePrintStream> file = WTF::FilePrintStream::open(actualFilename, "w");
    if (!file) {
        WTFLogAlways("Warning: Could not open page load performance data file %s for writing.\n", actualFilename);
        return;
    }

    WTFLogAlways("*** Page load performance data output to \"%s\" ***\n", actualFilename);

    file->print("INDIVIDUAL URL LOAD TIMES:\n");

    CFTimeInterval pageLoadTime = m_endTimes.last() - m_startTimes.last();
    file->printf("Load Time = %.1f ms\t%s\n", pageLoadTime * 1000.0, static_cast<const char*>(m_url));

    double meanTime = 0;
    double squareMeanRootTime = 0;
    double geometricMeanTime = 0;
    if (m_pagesTimed) {
        meanTime = m_totalTime / m_pagesTimed;
        squareMeanRootTime = (m_totalSquareRootsOfTime / m_pagesTimed) * (m_totalSquareRootsOfTime / m_pagesTimed);
        geometricMeanTime = pow(m_geometricMeanProductSum, (1.0 / m_pagesTimed));
    }

    file->printf("FINISHED:    Total Time = %.1f ms\n", m_totalTime * 1000.0);
    file->printf("           Longest Time = %.1f ms\n", m_longestTime * 1000.0);
    file->printf("              Mean Time = %.1f ms\n", meanTime * 1000.0);
    file->printf("  Square-Mean-Root Time = %.1f ms\n", squareMeanRootTime * 1000.0);
    file->printf("    Geometric Mean Time = %.1f ms\n", geometricMeanTime * 1000.0);
    file->printf("---------------------------------------------------------------------------------------------------\n");

    file->flush();
}
