/* ------------------------------------------------------------------
 * Copyright (C) 2008 PacketVideo
 *
 * 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.
 * -------------------------------------------------------------------
 */
#include "pv_omxdefs.h"
#include "omx_component.h"
#include "pv_omxcore.h"
#include "pv_omxwrapperbase.h"

#include "pv_omxmastercore.h"

#include "qc_omxcore.h"

//Number of base instances
OMX_U32 g_NumMasterOMXInstances = 0;
void *g_Wrapper = NULL;
void *g_MasterRegistry = NULL;
void *g_OMXCompHandles = NULL;
OMX_U32 g_TotalNumOMXComponents = 0;

typedef struct PVOMXMasterRegistryStruct
{
    OMX_U8 CompName[PV_OMX_MAX_COMPONENT_NAME_LENGTH];
    OMX_U8 CompRole[PV_OMX_MAX_COMPONENT_NAME_LENGTH];
    OMX_U32 OMXCoreIndex;
} PVOMXMasterRegistryStruct;

typedef struct PVOMXCompHandles
{
    OMX_HANDLETYPE handle;
    OMX_U32 OMXCoreIndex;
} PVOMXCompHandles;

// this is the number of vendor OMX cores
#if HARDWARE_OMX
#define NUMBER_OF_OMX_CORES 2
#else
#define NUMBER_OF_OMX_CORES 1
#endif

#define MAX_NUMBER_OF_OMX_COMPONENTS 50

OMX_ERRORTYPE OMX_APIENTRY  PV_MasterOMX_Init()
{
    OMX_ERRORTYPE Status = OMX_ErrorNone;
    OMX_U32 jj;
    OMX_U32 index;
    OMX_U32 master_index = 0;

    g_NumMasterOMXInstances++;

    if (g_NumMasterOMXInstances == 1)
    {

        // array of ptrs to various cores
        PV_OMX_WrapperBase **pWrapper = (PV_OMX_WrapperBase **)malloc(NUMBER_OF_OMX_CORES * sizeof(PV_OMX_WrapperBase *));
        if (pWrapper == NULL)
        {
            return OMX_ErrorInsufficientResources;
        }
        // set the global ptr to this array
        g_Wrapper = (void*)pWrapper;

        PVOMXMasterRegistryStruct *pOMXMasterRegistry = (PVOMXMasterRegistryStruct *)malloc(MAX_NUMBER_OF_OMX_COMPONENTS * sizeof(PVOMXMasterRegistryStruct));
        if (pOMXMasterRegistry == NULL)
        {
            return OMX_ErrorInsufficientResources;
        }
        g_MasterRegistry = (void*)pOMXMasterRegistry;

        PVOMXCompHandles *pOMXCompHandles = (PVOMXCompHandles *)malloc(MAX_NUMBER_OF_OMX_COMPONENTS * sizeof(PVOMXCompHandles));
        if (pOMXCompHandles == NULL)
        {
            return OMX_ErrorInsufficientResources;
        }
        g_OMXCompHandles = (void*)pOMXCompHandles;
        // init the array
        memset(pOMXCompHandles, 0, MAX_NUMBER_OF_OMX_COMPONENTS*sizeof(PVOMXCompHandles));


        // initialize pointers to omx methods for different vendor OMX cores

        //pWrapper[0] = Vendor0_Wrapper::New();
        //pWrapper[1] = Vendor1_Wrapper::New();

        //NOTE: Instantiate PV as the last core
#if HARDWARE_OMX
        pWrapper[0] = QC_OMX_Wrapper::New();
#endif
        pWrapper[NUMBER_OF_OMX_CORES-1] = PV_OMX_Wrapper::New(); // initialize pointers to omx methods

        // loop over all cores
        master_index = 0;
        OMX_STRING ComponentName = (OMX_STRING) malloc(PV_OMX_MAX_COMPONENT_NAME_LENGTH * sizeof(OMX_U8));

        for (jj = 0; jj < NUMBER_OF_OMX_CORES; jj++)
        {
            // first call OMX_Init
            Status = (*(pWrapper[jj]->GetpOMX_Init()))();
            if (Status == OMX_ErrorNone)
            {
                // enumerate components to get their number etc.
                OMX_ERRORTYPE stat = OMX_ErrorNone;

                index = 0;
                while (stat != OMX_ErrorNoMore)
                {
                    // clear, then get next  component name
                    memset(ComponentName, 0, PV_OMX_MAX_COMPONENT_NAME_LENGTH*sizeof(OMX_U8));

                    stat = (*(pWrapper[jj]->GetpOMX_ComponentNameEnum()))(
                               ComponentName,
                               PV_OMX_MAX_COMPONENT_NAME_LENGTH,
                               index);
                    if (stat == OMX_ErrorNoMore)
                        break;

                    // check number roles of the component
                    OMX_U32 numRoles;
                    numRoles = 0;
                    stat = (*(pWrapper[jj]->GetpOMX_GetRolesOfComponent()))(
                               ComponentName,
                               &numRoles,
                               NULL);
                    if ((numRoles > 0) && (stat == OMX_ErrorNone))
                    {
                        // allocate space for roles of the component
                        OMX_U32 role;
                        OMX_U8 **ComponentRoles = (OMX_U8 **) malloc(numRoles * sizeof(OMX_U8 *));

                        for (role = 0;role < numRoles; role++)
                            ComponentRoles[role] = (OMX_U8 *) malloc(PV_OMX_MAX_COMPONENT_NAME_LENGTH * sizeof(OMX_U8));


                        // get the array of strings with component roles
                        stat = (*(pWrapper[jj]->GetpOMX_GetRolesOfComponent()))(
                                   ComponentName,
                                   &numRoles,
                                   ComponentRoles);

                        //register all components separately in master registry
                        if (stat == OMX_ErrorNone)
                        {
                            for (role = 0;role < numRoles; role++)
                            {
                                strncpy((OMX_STRING)pOMXMasterRegistry[master_index].CompName, ComponentName, PV_OMX_MAX_COMPONENT_NAME_LENGTH);
                                strncpy((OMX_STRING)pOMXMasterRegistry[master_index].CompRole, (OMX_STRING)ComponentRoles[role], PV_OMX_MAX_COMPONENT_NAME_LENGTH);
                                pOMXMasterRegistry[master_index].OMXCoreIndex = jj;
                                master_index++;
                            }
                        }

                        // dealloc space for component roles
                        for (role = 0;role < numRoles; role++)
                            free(ComponentRoles[role]);

                        free(ComponentRoles);


                    } // done with roles of component represented by index

                    index++; // get next component from the jj-th core

                } // done with all components from jj-th core

            } // end of if(Status==OMX_ErrorNone)

        }//end of for(jj=...
        // at this point, all cores were init, and all components registered

        free(ComponentName);
        g_TotalNumOMXComponents = master_index;
    }

    return OMX_ErrorNone;
}

OMX_ERRORTYPE OMX_APIENTRY PV_MasterOMX_Deinit()
{
    OMX_U32 jj;
    OMX_ERRORTYPE Status = OMX_ErrorNone;

    g_NumMasterOMXInstances--;
    if (g_NumMasterOMXInstances == 0)
    {
        //free master registry
        g_TotalNumOMXComponents = 0;
        PVOMXMasterRegistryStruct *pOMXMasterRegistry = (PVOMXMasterRegistryStruct *) g_MasterRegistry;
        if (pOMXMasterRegistry)
            free(pOMXMasterRegistry);
        g_MasterRegistry = NULL;

        PVOMXCompHandles *pOMXCompHandles = (PVOMXCompHandles *)g_OMXCompHandles;
        if (pOMXCompHandles)
            free(pOMXCompHandles);
        g_OMXCompHandles = NULL;

        PV_OMX_WrapperBase **pWrapper = (PV_OMX_WrapperBase **) g_Wrapper;
        //call Deinit for each core
        if (pWrapper)
        {
            for (jj = 0; jj < NUMBER_OF_OMX_CORES; jj++)
            {
                Status = (*(pWrapper[jj]->GetpOMX_Deinit()))();
                pWrapper[jj]->Delete();
            }

            free(pWrapper);
            g_Wrapper = NULL;
        }


    }
    return OMX_ErrorNone;
}

// look for the component
OMX_API OMX_ERRORTYPE PV_MasterOMX_GetComponentsOfRole(
    OMX_IN	OMX_STRING role,
    OMX_INOUT	OMX_U32	*pNumComps,
    OMX_INOUT	OMX_U8	**compNames)
{

    OMX_U32 ii;
    // initialize
    *pNumComps = 0;
    PVOMXMasterRegistryStruct *pOMXMasterRegistry = (PVOMXMasterRegistryStruct *) g_MasterRegistry;
    if (pOMXMasterRegistry == NULL)
    {
        return OMX_ErrorNone;
    }


    // go through all components and check if they support the given role
    for (ii = 0; ii < g_TotalNumOMXComponents; ii ++)
    {
        // if the role matches, increment the counter and record the comp. name
        if (!strcmp((OMX_STRING)pOMXMasterRegistry[ii].CompRole, role))
        {
            // if a placeholder for compNames is provided, copy the component name into it
            if (compNames != NULL)
            {
                strcpy((OMX_STRING) compNames[*pNumComps], (OMX_STRING)pOMXMasterRegistry[ii].CompName);
            }
            // increment the counter
            *pNumComps = (*pNumComps + 1);

        }
    }

    return OMX_ErrorNone;

}


OMX_API OMX_ERRORTYPE OMX_APIENTRY 	PV_MasterOMX_GetHandle(
    OMX_OUT OMX_HANDLETYPE* pHandle,
    OMX_IN  OMX_STRING cComponentName,
    OMX_IN  OMX_PTR pAppData,
    OMX_IN  OMX_CALLBACKTYPE* pCallBacks)
{
    OMX_ERRORTYPE Status = OMX_ErrorNone;
    OMX_U32 ii, kk;

    PVOMXMasterRegistryStruct *pOMXMasterRegistry = (PVOMXMasterRegistryStruct *) g_MasterRegistry;
    if (pOMXMasterRegistry == NULL)
    {
        return OMX_ErrorComponentNotFound;
    }
    PVOMXCompHandles *pOMXCompHandles = (PVOMXCompHandles *)g_OMXCompHandles;
    if (pOMXCompHandles == NULL)
    {
        return OMX_ErrorComponentNotFound;
    }

    for (ii = 0; ii < g_TotalNumOMXComponents; ii ++)
    {
        // go through the list of supported components and find the component based on its name (identifier)
        if (!strcmp((OMX_STRING) pOMXMasterRegistry[ii].CompName, cComponentName))
        {
            // found a matching name
            break;
        }

    }

    if (ii == g_TotalNumOMXComponents)
    {
        // could not find a component with the given name
        return OMX_ErrorComponentNotFound;
    }

    // call the appropriate GetHandle for the component
    PV_OMX_WrapperBase **pWrapper = (PV_OMX_WrapperBase **) g_Wrapper;
    if (pWrapper)
    {
        //save component handle with the OMX core index, so it can be retrieved
        // later when freehandle is called
        // find an empty slot to write the pair handle/index:
        for (kk = 0;kk < MAX_NUMBER_OF_OMX_COMPONENTS; kk++)
        {
            if (pOMXCompHandles[kk].handle == NULL)
            {
                break;
            }
        }
        if (kk == MAX_NUMBER_OF_OMX_COMPONENTS)
        {
            return OMX_ErrorComponentNotFound;
        }

        OMX_U32 index = pOMXMasterRegistry[ii].OMXCoreIndex;
        Status = (*(pWrapper[index]->GetpOMX_GetHandle()))(pHandle, cComponentName, pAppData, pCallBacks);
        if (Status == OMX_ErrorNone)
        {
            // write the pair handle/index
            pOMXCompHandles[kk].handle = *pHandle;
            pOMXCompHandles[kk].OMXCoreIndex = index;
        }
        return Status;
    }
    else
    {
        return OMX_ErrorInsufficientResources;
    }

}

OMX_API OMX_ERRORTYPE OMX_APIENTRY PV_MasterOMX_FreeHandle(OMX_IN OMX_HANDLETYPE hComponent)
{

    OMX_ERRORTYPE Status = OMX_ErrorNone;
    OMX_U32 ii;
// here, we need to first find the handle among instantiated components
// then we retrieve the core based on component handle
// finally, call the OMX_FreeHandle for appropriate core
    PVOMXCompHandles *pOMXCompHandles = (PVOMXCompHandles *)g_OMXCompHandles;
    if (pOMXCompHandles == NULL)
    {
        return OMX_ErrorComponentNotFound;
    }
    for (ii = 0; ii < MAX_NUMBER_OF_OMX_COMPONENTS; ii ++)
    {
        // go through the list of supported components and find the component handle
        if (pOMXCompHandles[ii].handle == hComponent)
        {
            // found a matching handle
            break;
        }

    }
    if (ii == MAX_NUMBER_OF_OMX_COMPONENTS)
    {
        // could not find a component with the given name
        return OMX_ErrorComponentNotFound;
    }

    // call the appropriate GetHandle for the component
    PV_OMX_WrapperBase **pWrapper = (PV_OMX_WrapperBase **) g_Wrapper;
    if (pWrapper)
    {
        OMX_U32 index = pOMXCompHandles[ii].OMXCoreIndex;
        Status = (*(pWrapper[index]->GetpOMX_FreeHandle()))(hComponent);
        //we're done with this, so get rid of the component handle
        pOMXCompHandles[ii].handle = NULL;
        return Status;
    }
    else
    {
        return OMX_ErrorInsufficientResources;
    }

}

