/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *     http://aws.amazon.com/apache2.0/
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

#ifndef AVS_CAPABILITIES_DAVSCLIENT_ACSDKASSETSCOMMON_TEST_MOCKS_DAVSSERVICEMOCK_H_
#define AVS_CAPABILITIES_DAVSCLIENT_ACSDKASSETSCOMMON_TEST_MOCKS_DAVSSERVICEMOCK_H_

#include <chrono>
#include <istream>
#include <map>
#include <set>
#include <string>
#include <unordered_map>

#include "acsdkAssetsInterfaces/DavsRequest.h"

namespace alexaClientSDK {
namespace acsdkAssets {
namespace common {

class DavsServiceMock {
public:
    using FilterMap = commonInterfaces::DavsRequest::FilterMap;

    // Initializes empty service in /tmp/davs_service_mock
    DavsServiceMock();

    // Cleans up files
    virtual ~DavsServiceMock();

    /**
     * This mimics the step of uploading artifact to DAVS.
     * See https://w.amazon.com/bin/view/DeviceArtifactVendingService/DAVS2.0_SOP/#HPUTAPI-Uploadartifact
     *
     * @param type the type of artifact such as "wakeword" or "fingerprint"
     * @param key the key such as "alexa" or "amazon"
     * @param filterMap ordered map of filters
     * @param filePath absolute path to a file to upload, such as "/tmp/file.tar.gz"
     * @param ttlDelta the delta time from current time when artifact expires
     * @param id OPTIONAL, id of the artifact as it sits in the cloud, if not provided, then a concatination of
     * key+type+metadata is used
     *
     * Some analysis of fields expected by actual publishing call and how it affects the flow and if it matters to our
     * mocking: clientArtifactId: DAVS expects that publisher creates the ID; we'll create the ID automatically by using
     * the type_key_locale artifactMD5Checksum: DAVS uses this for validation of the upload; we don't care and we'll not
     * use artifactKey: we'll use 'key' supplied by the consumer of this API; will be returned in response artifactType:
     * we'll use 'type'; will be returned in response uploaderId: ignored description: ignored contentLength: we'll
     * populate automatically and return in response artifactTimeToLive: we'll use supplied delta from current time
     * metadata: given by the consumer of this API
     *
     * After this method is called, it is expected that CURL request to
     * https://api.amazonalexa.com/v2/deviceArtifacts/?artifactFilter=<request> will inspect the <request> part and
     * return a response JSON containing following valid fields: "artifactSize" will be the size of the local file
     * "artifactKey" and "artifactType" will be the same as given here (BTW, client side doesn't care right now but
     * might in future for further validation) "artifactTimeToLive" and "urlExpiryEpoch" will be currentTime + given
     * delta, returned in MS like DAVS does "artifactIdentifier" will be the ID generated by this API and will
     * internally be stored in /tmp/davs_service_mock "downloadUrl" will be something like
     * "https://device-artifacts-v2.s3.amazonaws.com/type-key-ID.tar.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20180919T223612Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Credential=AKIAJTPKJI7A3WTMPCQQ%2F20180919%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Signature=87160eda6c8325e9ce61120974cdf2f81c4b8a3d47c1192f6cf4b7500ed17165"
     *
     * Once client issues a request to that download URL, it is expected that the content of the original file pointed
     * to by filePath is returned. Once uploadBinaryArtifact() completes, the file is no longer needed and can be
     * deleted.  DAVS will make its own copy.
     */
    void uploadBinaryArtifact(
            const std::string& type,
            const std::string& key,
            const FilterMap& metadata,
            const std::string& filePath,
            std::chrono::milliseconds ttlDelta,
            const std::string& id = "");

    // The same as above, except that the file is expected to be given as base64-encoded string.  For convenience, we
    // expect that the caller uses Base64Url helper class to encode.
    void uploadBase64Artifact(
            const std::string& type,
            const std::string& key,
            const FilterMap& metadata,
            const std::string& encodedBinary,
            std::chrono::milliseconds ttlDelta,
            const std::string& id = "");

    static std::string getId(const FilterMap& map);

private:
    void uploadArtifact(
            const std::string& type,
            const std::string& key,
            const FilterMap& metadata,
            const std::istream& input,
            std::chrono::milliseconds ttlDelta,
            const std::string& id = "");
};

}  // namespace common
}  // namespace acsdkAssets
}  // namespace alexaClientSDK

#endif  // AVS_CAPABILITIES_DAVSCLIENT_ACSDKASSETSCOMMON_TEST_MOCKS_DAVSSERVICEMOCK_H_
