/* Copyright (c) 2014, 2016-2017 The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of The Linux Foundation, nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
 *
 */

#ifndef LOC_ADAPTER_PROXY_BASE_H
#define LOC_ADAPTER_PROXY_BASE_H

#include <ContextBase.h>
#include <gps_extended.h>

namespace loc_core {

class LocAdapterProxyBase {
private:
    LocAdapterBase *mLocAdapterBase;
protected:
    inline LocAdapterProxyBase(const LOC_API_ADAPTER_EVENT_MASK_T mask,
                               ContextBase* context, bool isMaster = false):
            mLocAdapterBase(new LocAdapterBase(mask, context, isMaster, this)) {
    }
    inline virtual ~LocAdapterProxyBase() {
        delete mLocAdapterBase;
    }
    inline void updateEvtMask(LOC_API_ADAPTER_EVENT_MASK_T event,
                              loc_registration_mask_status isEnabled) {
        mLocAdapterBase->updateEvtMask(event,isEnabled);
    }

    inline uint32_t generateSessionId() {
        return mLocAdapterBase->generateSessionId();
    }
public:
    inline ContextBase* getContext() const {
        return mLocAdapterBase->getContext();
    }

    inline virtual void handleEngineUpEvent() {};
    inline virtual void handleEngineDownEvent() {};
    inline virtual void reportPositionEvent(UlpLocation &location,
                                            GpsLocationExtended &locationExtended,
                                            enum loc_sess_status status,
                                            LocPosTechMask loc_technology_mask) {
        (void)location;
        (void)locationExtended;
        (void)status;
        (void)loc_technology_mask;
    }
};

} // namespace loc_core

#endif //LOC_ADAPTER_PROXY_BASE_H
