import { requestBuilder as rb } from "@smithy/core";
import { _json, collectBody, decorateServiceException as __decorateServiceException, expectInt32 as __expectInt32, expectLong as __expectLong, expectNonNull as __expectNonNull, expectNumber as __expectNumber, expectObject as __expectObject, expectString as __expectString, map, parseEpochTimestamp as __parseEpochTimestamp, take, withBaseException, } from "@smithy/smithy-client";
import { CloudFrontKeyValueStoreServiceException as __BaseException } from "../models/CloudFrontKeyValueStoreServiceException";
import { AccessDeniedException, ConflictException, InternalServerException, ResourceNotFoundException, ServiceQuotaExceededException, ValidationException, } from "../models/models_0";
export const se_DeleteKeyCommand = async (input, context) => {
    const b = rb(input, context);
    const headers = map({}, isSerializableHeaderValue, {
        [_im]: input[_IM],
    });
    b.bp("/key-value-stores/{KvsARN}/keys/{Key}");
    b.p("KvsARN", () => input.KvsARN, "{KvsARN}", false);
    b.p("Key", () => input.Key, "{Key}", false);
    let body;
    b.m("DELETE").h(headers).b(body);
    return b.build();
};
export const se_DescribeKeyValueStoreCommand = async (input, context) => {
    const b = rb(input, context);
    const headers = {};
    b.bp("/key-value-stores/{KvsARN}");
    b.p("KvsARN", () => input.KvsARN, "{KvsARN}", false);
    let body;
    b.m("GET").h(headers).b(body);
    return b.build();
};
export const se_GetKeyCommand = async (input, context) => {
    const b = rb(input, context);
    const headers = {};
    b.bp("/key-value-stores/{KvsARN}/keys/{Key}");
    b.p("KvsARN", () => input.KvsARN, "{KvsARN}", false);
    b.p("Key", () => input.Key, "{Key}", false);
    let body;
    b.m("GET").h(headers).b(body);
    return b.build();
};
export const se_ListKeysCommand = async (input, context) => {
    const b = rb(input, context);
    const headers = {};
    b.bp("/key-value-stores/{KvsARN}/keys");
    b.p("KvsARN", () => input.KvsARN, "{KvsARN}", false);
    const query = map({
        [_NT]: [, input[_NT]],
        [_MR]: [() => input.MaxResults !== void 0, () => input[_MR].toString()],
    });
    let body;
    b.m("GET").h(headers).q(query).b(body);
    return b.build();
};
export const se_PutKeyCommand = async (input, context) => {
    const b = rb(input, context);
    const headers = map({}, isSerializableHeaderValue, {
        "content-type": "application/json",
        [_im]: input[_IM],
    });
    b.bp("/key-value-stores/{KvsARN}/keys/{Key}");
    b.p("Key", () => input.Key, "{Key}", false);
    b.p("KvsARN", () => input.KvsARN, "{KvsARN}", false);
    let body;
    body = JSON.stringify(take(input, {
        Value: [],
    }));
    b.m("PUT").h(headers).b(body);
    return b.build();
};
export const se_UpdateKeysCommand = async (input, context) => {
    const b = rb(input, context);
    const headers = map({}, isSerializableHeaderValue, {
        "content-type": "application/json",
        [_im]: input[_IM],
    });
    b.bp("/key-value-stores/{KvsARN}/keys");
    b.p("KvsARN", () => input.KvsARN, "{KvsARN}", false);
    let body;
    body = JSON.stringify(take(input, {
        Deletes: (_) => _json(_),
        Puts: (_) => _json(_),
    }));
    b.m("POST").h(headers).b(body);
    return b.build();
};
export const de_DeleteKeyCommand = async (output, context) => {
    if (output.statusCode !== 200 && output.statusCode >= 300) {
        return de_CommandError(output, context);
    }
    const contents = map({
        $metadata: deserializeMetadata(output),
        [_ET]: [, output.headers[_e]],
    });
    const data = __expectNonNull(__expectObject(await parseBody(output.body, context)), "body");
    const doc = take(data, {
        ItemCount: __expectInt32,
        TotalSizeInBytes: __expectLong,
    });
    Object.assign(contents, doc);
    return contents;
};
export const de_DescribeKeyValueStoreCommand = async (output, context) => {
    if (output.statusCode !== 200 && output.statusCode >= 300) {
        return de_CommandError(output, context);
    }
    const contents = map({
        $metadata: deserializeMetadata(output),
        [_ET]: [, output.headers[_e]],
    });
    const data = __expectNonNull(__expectObject(await parseBody(output.body, context)), "body");
    const doc = take(data, {
        Created: (_) => __expectNonNull(__parseEpochTimestamp(__expectNumber(_))),
        FailureReason: __expectString,
        ItemCount: __expectInt32,
        KvsARN: __expectString,
        LastModified: (_) => __expectNonNull(__parseEpochTimestamp(__expectNumber(_))),
        Status: __expectString,
        TotalSizeInBytes: __expectLong,
    });
    Object.assign(contents, doc);
    return contents;
};
export const de_GetKeyCommand = async (output, context) => {
    if (output.statusCode !== 200 && output.statusCode >= 300) {
        return de_CommandError(output, context);
    }
    const contents = map({
        $metadata: deserializeMetadata(output),
    });
    const data = __expectNonNull(__expectObject(await parseBody(output.body, context)), "body");
    const doc = take(data, {
        ItemCount: __expectInt32,
        Key: __expectString,
        TotalSizeInBytes: __expectLong,
        Value: __expectString,
    });
    Object.assign(contents, doc);
    return contents;
};
export const de_ListKeysCommand = async (output, context) => {
    if (output.statusCode !== 200 && output.statusCode >= 300) {
        return de_CommandError(output, context);
    }
    const contents = map({
        $metadata: deserializeMetadata(output),
    });
    const data = __expectNonNull(__expectObject(await parseBody(output.body, context)), "body");
    const doc = take(data, {
        Items: _json,
        NextToken: __expectString,
    });
    Object.assign(contents, doc);
    return contents;
};
export const de_PutKeyCommand = async (output, context) => {
    if (output.statusCode !== 200 && output.statusCode >= 300) {
        return de_CommandError(output, context);
    }
    const contents = map({
        $metadata: deserializeMetadata(output),
        [_ET]: [, output.headers[_e]],
    });
    const data = __expectNonNull(__expectObject(await parseBody(output.body, context)), "body");
    const doc = take(data, {
        ItemCount: __expectInt32,
        TotalSizeInBytes: __expectLong,
    });
    Object.assign(contents, doc);
    return contents;
};
export const de_UpdateKeysCommand = async (output, context) => {
    if (output.statusCode !== 200 && output.statusCode >= 300) {
        return de_CommandError(output, context);
    }
    const contents = map({
        $metadata: deserializeMetadata(output),
        [_ET]: [, output.headers[_e]],
    });
    const data = __expectNonNull(__expectObject(await parseBody(output.body, context)), "body");
    const doc = take(data, {
        ItemCount: __expectInt32,
        TotalSizeInBytes: __expectLong,
    });
    Object.assign(contents, doc);
    return contents;
};
const de_CommandError = async (output, context) => {
    const parsedOutput = {
        ...output,
        body: await parseErrorBody(output.body, context),
    };
    const errorCode = loadRestJsonErrorCode(output, parsedOutput.body);
    switch (errorCode) {
        case "AccessDeniedException":
        case "com.amazonaws.cloudfrontkeyvaluestore#AccessDeniedException":
            throw await de_AccessDeniedExceptionRes(parsedOutput, context);
        case "ConflictException":
        case "com.amazonaws.cloudfrontkeyvaluestore#ConflictException":
            throw await de_ConflictExceptionRes(parsedOutput, context);
        case "InternalServerException":
        case "com.amazonaws.cloudfrontkeyvaluestore#InternalServerException":
            throw await de_InternalServerExceptionRes(parsedOutput, context);
        case "ResourceNotFoundException":
        case "com.amazonaws.cloudfrontkeyvaluestore#ResourceNotFoundException":
            throw await de_ResourceNotFoundExceptionRes(parsedOutput, context);
        case "ServiceQuotaExceededException":
        case "com.amazonaws.cloudfrontkeyvaluestore#ServiceQuotaExceededException":
            throw await de_ServiceQuotaExceededExceptionRes(parsedOutput, context);
        case "ValidationException":
        case "com.amazonaws.cloudfrontkeyvaluestore#ValidationException":
            throw await de_ValidationExceptionRes(parsedOutput, context);
        default:
            const parsedBody = parsedOutput.body;
            return throwDefaultError({
                output,
                parsedBody,
                errorCode,
            });
    }
};
const throwDefaultError = withBaseException(__BaseException);
const de_AccessDeniedExceptionRes = async (parsedOutput, context) => {
    const contents = map({});
    const data = parsedOutput.body;
    const doc = take(data, {
        Message: __expectString,
    });
    Object.assign(contents, doc);
    const exception = new AccessDeniedException({
        $metadata: deserializeMetadata(parsedOutput),
        ...contents,
    });
    return __decorateServiceException(exception, parsedOutput.body);
};
const de_ConflictExceptionRes = async (parsedOutput, context) => {
    const contents = map({});
    const data = parsedOutput.body;
    const doc = take(data, {
        Message: __expectString,
    });
    Object.assign(contents, doc);
    const exception = new ConflictException({
        $metadata: deserializeMetadata(parsedOutput),
        ...contents,
    });
    return __decorateServiceException(exception, parsedOutput.body);
};
const de_InternalServerExceptionRes = async (parsedOutput, context) => {
    const contents = map({});
    const data = parsedOutput.body;
    const doc = take(data, {
        Message: __expectString,
    });
    Object.assign(contents, doc);
    const exception = new InternalServerException({
        $metadata: deserializeMetadata(parsedOutput),
        ...contents,
    });
    return __decorateServiceException(exception, parsedOutput.body);
};
const de_ResourceNotFoundExceptionRes = async (parsedOutput, context) => {
    const contents = map({});
    const data = parsedOutput.body;
    const doc = take(data, {
        Message: __expectString,
    });
    Object.assign(contents, doc);
    const exception = new ResourceNotFoundException({
        $metadata: deserializeMetadata(parsedOutput),
        ...contents,
    });
    return __decorateServiceException(exception, parsedOutput.body);
};
const de_ServiceQuotaExceededExceptionRes = async (parsedOutput, context) => {
    const contents = map({});
    const data = parsedOutput.body;
    const doc = take(data, {
        Message: __expectString,
    });
    Object.assign(contents, doc);
    const exception = new ServiceQuotaExceededException({
        $metadata: deserializeMetadata(parsedOutput),
        ...contents,
    });
    return __decorateServiceException(exception, parsedOutput.body);
};
const de_ValidationExceptionRes = async (parsedOutput, context) => {
    const contents = map({});
    const data = parsedOutput.body;
    const doc = take(data, {
        Message: __expectString,
    });
    Object.assign(contents, doc);
    const exception = new ValidationException({
        $metadata: deserializeMetadata(parsedOutput),
        ...contents,
    });
    return __decorateServiceException(exception, parsedOutput.body);
};
const deserializeMetadata = (output) => ({
    httpStatusCode: output.statusCode,
    requestId: output.headers["x-amzn-requestid"] ?? output.headers["x-amzn-request-id"] ?? output.headers["x-amz-request-id"],
    extendedRequestId: output.headers["x-amz-id-2"],
    cfId: output.headers["x-amz-cf-id"],
});
const collectBodyString = (streamBody, context) => collectBody(streamBody, context).then((body) => context.utf8Encoder(body));
const isSerializableHeaderValue = (value) => value !== undefined &&
    value !== null &&
    value !== "" &&
    (!Object.getOwnPropertyNames(value).includes("length") || value.length != 0) &&
    (!Object.getOwnPropertyNames(value).includes("size") || value.size != 0);
const _ET = "ETag";
const _IM = "IfMatch";
const _MR = "MaxResults";
const _NT = "NextToken";
const _e = "etag";
const _im = "if-match";
const parseBody = (streamBody, context) => collectBodyString(streamBody, context).then((encoded) => {
    if (encoded.length) {
        return JSON.parse(encoded);
    }
    return {};
});
const parseErrorBody = async (errorBody, context) => {
    const value = await parseBody(errorBody, context);
    value.message = value.message ?? value.Message;
    return value;
};
const loadRestJsonErrorCode = (output, data) => {
    const findKey = (object, key) => Object.keys(object).find((k) => k.toLowerCase() === key.toLowerCase());
    const sanitizeErrorCode = (rawValue) => {
        let cleanValue = rawValue;
        if (typeof cleanValue === "number") {
            cleanValue = cleanValue.toString();
        }
        if (cleanValue.indexOf(",") >= 0) {
            cleanValue = cleanValue.split(",")[0];
        }
        if (cleanValue.indexOf(":") >= 0) {
            cleanValue = cleanValue.split(":")[0];
        }
        if (cleanValue.indexOf("#") >= 0) {
            cleanValue = cleanValue.split("#")[1];
        }
        return cleanValue;
    };
    const headerKey = findKey(output.headers, "x-amzn-errortype");
    if (headerKey !== undefined) {
        return sanitizeErrorCode(output.headers[headerKey]);
    }
    if (data.code !== undefined) {
        return sanitizeErrorCode(data.code);
    }
    if (data["__type"] !== undefined) {
        return sanitizeErrorCode(data["__type"]);
    }
};
