/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License 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.
 */

#define LOG_TAG "NStorage"

#include <android/storage_manager.h>
#include <storage/IMountService.h>

#include <binder/Binder.h>
#include <binder/IServiceManager.h>
#include <utils/Atomic.h>
#include <utils/Log.h>
#include <utils/RefBase.h>
#include <utils/String8.h>
#include <utils/String16.h>
#include <utils/Vector.h>
#include <utils/threads.h>


using namespace android;

struct ObbActionListener : public BnObbActionListener {
private:
    sp<AStorageManager> mStorageManager;

public:
    ObbActionListener(AStorageManager* mgr) :
            mStorageManager(mgr)
    {}

    virtual void onObbResult(const android::String16& filename, const int32_t nonce,
            const int32_t state);
};

class ObbCallback {
public:
    ObbCallback(int32_t _nonce, AStorageManager_obbCallbackFunc _cb, void* _data)
            : nonce(_nonce)
            , cb(_cb)
            , data(_data)
    {}

    int32_t nonce;
    AStorageManager_obbCallbackFunc cb;
    void* data;
};

struct AStorageManager : public RefBase {
protected:
    Mutex mCallbackLock;
    Vector<ObbCallback*> mCallbacks;
    volatile int32_t mNextNonce;
    sp<ObbActionListener> mObbActionListener;
    sp<IMountService> mMountService;

    int32_t getNextNonce() {
        return android_atomic_inc(&mNextNonce);
    }

    ObbCallback* registerObbCallback(AStorageManager_obbCallbackFunc func, void* data) {
        ObbCallback* cb = new ObbCallback(getNextNonce(), func, data);
        {
            AutoMutex _l(mCallbackLock);
            mCallbacks.push(cb);
        }
        return cb;
    }

public:
    AStorageManager()
    {
    }

    bool initialize() {
        sp<IServiceManager> sm = defaultServiceManager();
        if (sm == NULL) {
            LOGE("Couldn't get default ServiceManager\n");
            return false;
        }

        mMountService = interface_cast<IMountService>(sm->getService(String16("mount")));
        if (mMountService == NULL) {
            LOGE("Couldn't get connection to MountService\n");
            return false;
        }

        mObbActionListener = new ObbActionListener(this);

        return true;
    }

    void fireCallback(const char* filename, const int32_t nonce, const int32_t state) {
        ObbCallback* target = NULL;
        {
            AutoMutex _l(mCallbackLock);
            int N = mCallbacks.size();
            for (int i = 0; i < N; i++) {
                ObbCallback* cb = mCallbacks.editItemAt(i);
                if (cb->nonce == nonce) {
                    target = cb;
                    mCallbacks.removeAt(i);
                    break;
                }
            }
        }

        if (target != NULL) {
            target->cb(filename, state, target->data);
            delete target;
        } else {
            LOGI("Didn't find the callback handler for: %s\n", filename);
        }
    }

    void mountObb(const char* filename, const char* key, AStorageManager_obbCallbackFunc func, void* data) {
        ObbCallback* cb = registerObbCallback(func, data);
        String16 filename16(filename);
        String16 key16(key);
        mMountService->mountObb(filename16, key16, mObbActionListener, cb->nonce);
    }

    void unmountObb(const char* filename, const bool force, AStorageManager_obbCallbackFunc func, void* data) {
        ObbCallback* cb = registerObbCallback(func, data);
        String16 filename16(filename);
        mMountService->unmountObb(filename16, force, mObbActionListener, cb->nonce);
    }

    int isObbMounted(const char* filename) {
        String16 filename16(filename);
        return mMountService->isObbMounted(filename16);
    }

    const char* getMountedObbPath(const char* filename) {
        String16 filename16(filename);
        String16 path16;
        if (mMountService->getMountedObbPath(filename16, path16)) {
            return String8(path16).string();
        } else {
            return NULL;
        }
    }
};

void ObbActionListener::onObbResult(const android::String16& filename, const int32_t nonce, const int32_t state) {
    mStorageManager->fireCallback(String8(filename).string(), nonce, state);
}


AStorageManager* AStorageManager_new() {
    sp<AStorageManager> mgr = new AStorageManager();
    if (mgr == NULL || !mgr->initialize()) {
        return NULL;
    }
    mgr->incStrong((void*)AStorageManager_new);
    return static_cast<AStorageManager*>(mgr.get());
}

void AStorageManager_delete(AStorageManager* mgr) {
    if (mgr) {
        mgr->decStrong((void*)AStorageManager_new);
    }
}

void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key,
        AStorageManager_obbCallbackFunc cb, void* data) {
    mgr->mountObb(filename, key, cb, data);
}

void AStorageManager_unmountObb(AStorageManager* mgr, const char* filename, const int force,
        AStorageManager_obbCallbackFunc cb, void* data) {
    mgr->unmountObb(filename, force != 0, cb, data);
}

int AStorageManager_isObbMounted(AStorageManager* mgr, const char* filename) {
    return mgr->isObbMounted(filename) != 0;
}

const char* AStorageManager_getMountedObbPath(AStorageManager* mgr, const char* filename) {
    return mgr->getMountedObbPath(filename);
}
