/*
 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
 *
 * This software is dual-licensed to you under the MIT License (MIT) and
 * the Universal Permissive License (UPL). See the LICENSE file in the root
 * directory for license terms. You may choose either license, or both.
 */

#pragma once

#include <ExternalObject.hpp>
#include <StorageObject.hpp>
#include <VirtualDevice.hpp>
#include <iotcs/VirtualDeviceImpl.hpp>
#include <mutex>
#include <type_traits>
#include <vector>
#include <string>
#include <map>
#include "iotcs_storage_object.h"
#include "advanced/iotcs_storage_object.h"

#ifdef __MBED__
#include "mbed.h"
#include "rtos.h"
#define MUTEX_TYPE Mutex
#else
#define MUTEX_TYPE std::mutex
#endif

namespace iotdcl {
    class SyncEventImpl : public SyncEvent<VirtualDevice> {
        private:
            VirtualDevice *vd;
            const std::string *name;
            StorageObject *so;
        public:
            SyncEventImpl(const std::string &name, VirtualDevice *vd, StorageObject *so) {
                this->vd = vd;
                this->so = so;
                this->name = new std::string(name);
            }

            virtual VirtualDevice* getVirtualDevice() const {
                return vd;
            }

            virtual const std::string& getName() const {
                return *name;
            }

            virtual StorageObject* getSource() const {
                return so;
            }

            virtual ~SyncEventImpl() {
                delete this->name;
            }
    };
    class StorageObjectImpl : public StorageObject {
        friend StorageObject;
        friend VirtualDevice;
        private:
            static MUTEX_TYPE mapMutex;
            static void onSyncCallback(iotcs_storage_object_sync_event *event);
            static std::map<iotcs_storage_object_handle, StorageObjectImpl*> globalSO;
            static std::map<iotcs_storage_object_handle, const SyncCallback*> globalOnSyncCallbacks;
        public:
            VirtualDevice* getVirtualDevice() const;
            virtual ~StorageObjectImpl() {};
            StorageObjectImpl(const std::string &name, const std::string &contentType);
            StorageObjectImpl(iotcs_storage_object_handle storage_object_handle);
            StorageObjectImpl(const std::string &uri);
    };
};
