/*
 * Copyright (C) 2021 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 "config.h"
#include "ModelDocument.h"

#if ENABLE(MODEL_ELEMENT)

#include "Document.h"
#include "DocumentLoader.h"
#include "EventNames.h"
#include "FrameLoader.h"
#include "FrameLoaderClient.h"
#include "HTMLBodyElement.h"
#include "HTMLHeadElement.h"
#include "HTMLHtmlElement.h"
#include "HTMLMetaElement.h"
#include "HTMLModelElement.h"
#include "HTMLNames.h"
#include "HTMLSourceElement.h"
#include "HTMLStyleElement.h"
#include "RawDataDocumentParser.h"
#include <wtf/IsoMallocInlines.h>
#include <wtf/text/StringBuilder.h>

namespace WebCore {

WTF_MAKE_ISO_ALLOCATED_IMPL(ModelDocument);

using namespace HTMLNames;

class ModelDocumentParser final : public RawDataDocumentParser {
public:
    static Ref<ModelDocumentParser> create(ModelDocument& document)
    {
        return adoptRef(*new ModelDocumentParser(document));
    }

private:
    ModelDocumentParser(ModelDocument& document)
        : RawDataDocumentParser { document }
        , m_outgoingReferrer { document.outgoingReferrer() }
    {
    }

    void createDocumentStructure();

    void appendBytes(DocumentWriter&, const uint8_t*, size_t) final;
    void finish() final;

    HTMLModelElement* m_modelElement { nullptr };
    String m_outgoingReferrer;
};

void ModelDocumentParser::createDocumentStructure()
{
    auto& document = *this->document();

    auto rootElement = HTMLHtmlElement::create(document);
    document.appendChild(rootElement);
    document.setCSSTarget(rootElement.ptr());
    rootElement->insertedByParser();

    if (document.frame())
        document.frame()->injectUserScripts(UserScriptInjectionTime::DocumentStart);

    auto headElement = HTMLHeadElement::create(document);
    rootElement->appendChild(headElement);

    auto metaElement = HTMLMetaElement::create(document);
    metaElement->setAttributeWithoutSynchronization(nameAttr, AtomString("viewport", AtomString::ConstructFromLiteral));
    metaElement->setAttributeWithoutSynchronization(contentAttr, AtomString("width=device-width,initial-scale=1", AtomString::ConstructFromLiteral));
    headElement->appendChild(metaElement);

    auto styleElement = HTMLStyleElement::create(document);
    auto styleContent = "body { background-color: white; text-align: center; }\n"
        "@media (prefers-color-scheme: dark) { body { background-color: rgb(32, 32, 37); } }\n"
        "model { width: 80vw; height: 80vh; }\n"_s;
    styleElement->setTextContent(styleContent);
    headElement->appendChild(styleElement);

    auto body = HTMLBodyElement::create(document);
    rootElement->appendChild(body);

    auto modelElement = HTMLModelElement::create(HTMLNames::modelTag, document);
    m_modelElement = modelElement.ptr();
    modelElement->setAttributeWithoutSynchronization(controlsAttr, emptyAtom());

    auto sourceElement = HTMLSourceElement::create(HTMLNames::sourceTag, document);
    sourceElement->setAttributeWithoutSynchronization(srcAttr, document.url().string());
    if (RefPtr loader = document.loader())
        sourceElement->setAttributeWithoutSynchronization(typeAttr, loader->responseMIMEType());

    modelElement->appendChild(sourceElement);

    body->appendChild(modelElement);
    document.setHasVisuallyNonEmptyCustomContent();

    auto frame = document.frame();
    if (!frame)
        return;

    frame->loader().activeDocumentLoader()->setMainResourceDataBufferingPolicy(DataBufferingPolicy::DoNotBufferData);
    frame->loader().setOutgoingReferrer(document.completeURL(m_outgoingReferrer));
}

void ModelDocumentParser::appendBytes(DocumentWriter&, const uint8_t*, size_t)
{
    if (!m_modelElement)
        createDocumentStructure();
}

void ModelDocumentParser::finish()
{
    document()->finishedParsing();
}

ModelDocument::ModelDocument(Frame* frame, const Settings& settings, const URL& url)
    : HTMLDocument(frame, settings, url, { DocumentClass::Model })
{
    if (frame)
        m_outgoingReferrer = frame->loader().outgoingReferrer();
}

Ref<DocumentParser> ModelDocument::createParser()
{
    return ModelDocumentParser::create(*this);
}

}

#endif
