/*
 * Copyright (C) 2021 Igalia S.L.
 * 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. AND ITS CONTRIBUTORS ``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 ITS 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 "TemporalInstantPrototype.h"

#include "ISO8601.h"
#include "IntlDateTimeFormat.h"
#include "JSCInlines.h"
#include "TemporalInstant.h"

namespace JSC {

static JSC_DECLARE_HOST_FUNCTION(temporalInstantPrototypeFuncAdd);
static JSC_DECLARE_HOST_FUNCTION(temporalInstantPrototypeFuncSubtract);
static JSC_DECLARE_HOST_FUNCTION(temporalInstantPrototypeFuncUntil);
static JSC_DECLARE_HOST_FUNCTION(temporalInstantPrototypeFuncSince);
static JSC_DECLARE_HOST_FUNCTION(temporalInstantPrototypeFuncRound);
static JSC_DECLARE_HOST_FUNCTION(temporalInstantPrototypeFuncEquals);
static JSC_DECLARE_HOST_FUNCTION(temporalInstantPrototypeFuncToString);
static JSC_DECLARE_HOST_FUNCTION(temporalInstantPrototypeFuncToJSON);
static JSC_DECLARE_HOST_FUNCTION(temporalInstantPrototypeFuncToLocaleString);
static JSC_DECLARE_HOST_FUNCTION(temporalInstantPrototypeFuncValueOf);
static JSC_DECLARE_CUSTOM_GETTER(temporalInstantPrototypeGetterEpochSeconds);
static JSC_DECLARE_CUSTOM_GETTER(temporalInstantPrototypeGetterEpochMilliseconds);
static JSC_DECLARE_CUSTOM_GETTER(temporalInstantPrototypeGetterEpochMicroseconds);
static JSC_DECLARE_CUSTOM_GETTER(temporalInstantPrototypeGetterEpochNanoseconds);

}

#include "TemporalInstantPrototype.lut.h"

namespace JSC {

const ClassInfo TemporalInstantPrototype::s_info = { "Temporal.Instant", &Base::s_info, &instantPrototypeTable, nullptr, CREATE_METHOD_TABLE(TemporalInstantPrototype) };

/* Source for TemporalInstantPrototype.lut.h
@begin instantPrototypeTable
  add                temporalInstantPrototypeFuncAdd                  DontEnum|Function 1
  subtract           temporalInstantPrototypeFuncSubtract             DontEnum|Function 1
  until              temporalInstantPrototypeFuncUntil                DontEnum|Function 1
  since              temporalInstantPrototypeFuncSince                DontEnum|Function 1
  round              temporalInstantPrototypeFuncRound                DontEnum|Function 1
  equals             temporalInstantPrototypeFuncEquals               DontEnum|Function 1
  toString           temporalInstantPrototypeFuncToString             DontEnum|Function 0
  toJSON             temporalInstantPrototypeFuncToJSON               DontEnum|Function 0
  toLocaleString     temporalInstantPrototypeFuncToLocaleString       DontEnum|Function 0
  valueOf            temporalInstantPrototypeFuncValueOf              DontEnum|Function 0
  epochSeconds       temporalInstantPrototypeGetterEpochSeconds       DontEnum|ReadOnly|CustomAccessor
  epochMilliseconds  temporalInstantPrototypeGetterEpochMilliseconds  DontEnum|ReadOnly|CustomAccessor
  epochMicroseconds  temporalInstantPrototypeGetterEpochMicroseconds  DontEnum|ReadOnly|CustomAccessor
  epochNanoseconds   temporalInstantPrototypeGetterEpochNanoseconds   DontEnum|ReadOnly|CustomAccessor
@end
*/

TemporalInstantPrototype* TemporalInstantPrototype::create(VM& vm, Structure* structure)
{
    auto* prototype = new (NotNull, allocateCell<TemporalInstantPrototype>(vm)) TemporalInstantPrototype(vm, structure);
    prototype->finishCreation(vm);
    return prototype;
}

Structure* TemporalInstantPrototype::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
{
    return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
}

TemporalInstantPrototype::TemporalInstantPrototype(VM& vm, Structure* structure)
    : Base(vm, structure)
{
}

void TemporalInstantPrototype::finishCreation(VM& vm)
{
    Base::finishCreation(vm);
    ASSERT(inherits(vm, info()));
    JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
}

static constexpr std::initializer_list<TemporalUnit> disallowedAdditionUnits = {
    TemporalUnit::Year,
    TemporalUnit::Month,
    TemporalUnit::Week,
    TemporalUnit::Day,
};

JSC_DEFINE_HOST_FUNCTION(temporalInstantPrototypeFuncAdd, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    TemporalInstant* instant = jsDynamicCast<TemporalInstant*>(vm, callFrame->thisValue());
    if (!instant)
        return throwVMTypeError(globalObject, scope, "Temporal.Instant.prototype.add called on value that's not a Instant"_s);

    ISO8601::Duration duration = TemporalDuration::toLimitedDuration(globalObject, callFrame->argument(0), disallowedAdditionUnits);
    RETURN_IF_EXCEPTION(scope, { });

    std::optional<ISO8601::ExactTime> newExactTime = instant->exactTime().add(duration);
    if (!newExactTime) {
        throwRangeError(globalObject, scope, "Addition is outside of supported range for Temporal.Instant"_s);
        return { };
    }

    RELEASE_AND_RETURN(scope, JSValue::encode(TemporalInstant::tryCreateIfValid(globalObject, *newExactTime)));
}

JSC_DEFINE_HOST_FUNCTION(temporalInstantPrototypeFuncSubtract, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    TemporalInstant* instant = jsDynamicCast<TemporalInstant*>(vm, callFrame->thisValue());
    if (!instant)
        return throwVMTypeError(globalObject, scope, "Temporal.Instant.prototype.subtract called on value that's not a Instant"_s);

    ISO8601::Duration duration = TemporalDuration::toLimitedDuration(globalObject, callFrame->argument(0), disallowedAdditionUnits);
    RETURN_IF_EXCEPTION(scope, { });

    std::optional<ISO8601::ExactTime> newExactTime = instant->exactTime().add(-duration);
    if (!newExactTime) {
        throwRangeError(globalObject, scope, "Subtraction is outside of supported range for Temporal.Instant"_s);
        return { };
    }

    RELEASE_AND_RETURN(scope, JSValue::encode(TemporalInstant::tryCreateIfValid(globalObject, *newExactTime)));
}

JSC_DEFINE_HOST_FUNCTION(temporalInstantPrototypeFuncUntil, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    TemporalInstant* instant = jsDynamicCast<TemporalInstant*>(vm, callFrame->thisValue());
    if (!instant)
        return throwVMTypeError(globalObject, scope, "Temporal.Instant.prototype.until called on value that's not a Instant"_s);

    TemporalInstant* other = TemporalInstant::toInstant(globalObject, callFrame->argument(0));
    RETURN_IF_EXCEPTION(scope, { });

    JSValue options = callFrame->argument(1);
    ISO8601::Duration result = instant->difference(globalObject, other, options);
    RETURN_IF_EXCEPTION(scope, { });

    return JSValue::encode(TemporalDuration::create(vm, globalObject->durationStructure(), WTFMove(result)));
}

JSC_DEFINE_HOST_FUNCTION(temporalInstantPrototypeFuncSince, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    TemporalInstant* instant = jsDynamicCast<TemporalInstant*>(vm, callFrame->thisValue());
    if (!instant)
        return throwVMTypeError(globalObject, scope, "Temporal.Instant.prototype.since called on value that's not a Instant"_s);

    TemporalInstant* other = TemporalInstant::toInstant(globalObject, callFrame->argument(0));
    RETURN_IF_EXCEPTION(scope, { });

    JSValue options = callFrame->argument(1);
    ISO8601::Duration result = other->difference(globalObject, instant, options);
    RETURN_IF_EXCEPTION(scope, { });

    return JSValue::encode(TemporalDuration::create(vm, globalObject->durationStructure(), WTFMove(result)));
}

JSC_DEFINE_HOST_FUNCTION(temporalInstantPrototypeFuncRound, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    TemporalInstant* instant = jsDynamicCast<TemporalInstant*>(vm, callFrame->thisValue());
    if (!instant)
        return throwVMTypeError(globalObject, scope, "Temporal.Instant.prototype.round called on value that's not a Instant"_s);

    JSValue options = callFrame->argument(0);
    if (options.isUndefined())
        return throwVMTypeError(globalObject, scope, "Temporal.Instant.prototype.round requires an options argument"_s);

    ISO8601::ExactTime newExactTime = instant->round(globalObject, options);
    RETURN_IF_EXCEPTION(scope, { });

    return JSValue::encode(TemporalInstant::create(vm, globalObject->instantStructure(), newExactTime));
}

JSC_DEFINE_HOST_FUNCTION(temporalInstantPrototypeFuncEquals, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    TemporalInstant* instant = jsDynamicCast<TemporalInstant*>(vm, callFrame->thisValue());
    if (!instant)
        return throwVMTypeError(globalObject, scope, "Temporal.Instant.prototype.equals called on value that's not a Instant"_s);

    TemporalInstant* other = TemporalInstant::toInstant(globalObject, callFrame->argument(0));
    RETURN_IF_EXCEPTION(scope, { });

    return JSValue::encode(jsBoolean(instant->exactTime() == other->exactTime()));
}

// Temporal.Instant.prototype.toString( [ options ] )
// https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.tostring
JSC_DEFINE_HOST_FUNCTION(temporalInstantPrototypeFuncToString, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    TemporalInstant* instant = jsDynamicCast<TemporalInstant*>(vm, callFrame->thisValue());
    if (!instant)
        return throwVMTypeError(globalObject, scope, "Temporal.Instant.prototype.toString called on value that's not a Instant"_s);

    RELEASE_AND_RETURN(scope, JSValue::encode(jsString(vm, instant->toString(globalObject, callFrame->argument(0)))));
}

JSC_DEFINE_HOST_FUNCTION(temporalInstantPrototypeFuncToJSON, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    TemporalInstant* instant = jsDynamicCast<TemporalInstant*>(vm, callFrame->thisValue());
    if (!instant)
        return throwVMTypeError(globalObject, scope, "Temporal.Instant.prototype.toJSON called on value that's not a Instant"_s);

    RELEASE_AND_RETURN(scope, JSValue::encode(jsString(vm, instant->toString())));
}

// FIXME: Is this better as a JSBuiltin?
JSC_DEFINE_HOST_FUNCTION(temporalInstantPrototypeFuncToLocaleString, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    TemporalInstant* instant = jsDynamicCast<TemporalInstant*>(vm, callFrame->thisValue());
    if (!instant)
        return throwVMTypeError(globalObject, scope, "Temporal.Instant.prototype.toLocaleString called on value that's not a Instant"_s);

    IntlDateTimeFormat* formatter = IntlDateTimeFormat::create(vm, globalObject->dateTimeFormatStructure());
    RETURN_IF_EXCEPTION(scope, { });

    formatter->initializeDateTimeFormat(globalObject, callFrame->argument(0), callFrame->argument(1));
    RETURN_IF_EXCEPTION(scope, { });

    // FIXME: change IntlDateTimeFormat to use epochNanoseconds
    RELEASE_AND_RETURN(scope, JSValue::encode(formatter->format(globalObject, instant->exactTime().epochMilliseconds())));
}

JSC_DEFINE_HOST_FUNCTION(temporalInstantPrototypeFuncValueOf, (JSGlobalObject* globalObject, CallFrame*))
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    return throwVMTypeError(globalObject, scope, "Temporal.Instant.prototype.valueOf must not be called. To compare Instant values, use Temporal.Instant.compare"_s);
}

JSC_DEFINE_CUSTOM_GETTER(temporalInstantPrototypeGetterEpochSeconds, (JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName))
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    TemporalInstant* instant = jsDynamicCast<TemporalInstant*>(vm, JSValue::decode(thisValue));
    if (!instant)
        return throwVMTypeError(globalObject, scope, "Temporal.Instant.prototype.epochSeconds called on value that's not a Instant"_s);

    return JSValue::encode(jsNumber(instant->exactTime().epochSeconds()));
}

JSC_DEFINE_CUSTOM_GETTER(temporalInstantPrototypeGetterEpochMilliseconds, (JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName))
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    TemporalInstant* instant = jsDynamicCast<TemporalInstant*>(vm, JSValue::decode(thisValue));
    if (!instant)
        return throwVMTypeError(globalObject, scope, "Temporal.Instant.prototype.epochMilliseconds called on value that's not a Instant"_s);

    return JSValue::encode(jsNumber(instant->exactTime().epochMilliseconds()));
}

JSC_DEFINE_CUSTOM_GETTER(temporalInstantPrototypeGetterEpochMicroseconds, (JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName))
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    TemporalInstant* instant = jsDynamicCast<TemporalInstant*>(vm, JSValue::decode(thisValue));
    if (!instant)
        return throwVMTypeError(globalObject, scope, "Temporal.Instant.prototype.epochMicroseconds called on value that's not a Instant"_s);

    RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::makeHeapBigIntOrBigInt32(globalObject, instant->exactTime().epochMicroseconds())));
}

JSC_DEFINE_CUSTOM_GETTER(temporalInstantPrototypeGetterEpochNanoseconds, (JSGlobalObject* globalObject, EncodedJSValue thisValue, PropertyName))
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    TemporalInstant* instant = jsDynamicCast<TemporalInstant*>(vm, JSValue::decode(thisValue));
    if (!instant)
        return throwVMTypeError(globalObject, scope, "Temporal.Instant.prototype.epochNanoseconds called on value that's not a Instant"_s);

    RELEASE_AND_RETURN(scope, JSValue::encode(JSBigInt::createFrom(globalObject, instant->exactTime().epochNanoseconds())));
}

} // namespace JSC
