/*
 * FUNCTION: PKIX_ProcessingParams_AddCertStore
 * (see comments in pkix_params.h)
 */
PKIX_Error *
PKIX_ProcessingParams_AddCertStore(
        PKIX_ProcessingParams *params,
        PKIX_CertStore *store,
        void *plContext)
{
        PKIX_List *certStores = NULL;

        PKIX_ENTER(PROCESSINGPARAMS, "PKIX_ProcessingParams_AddCertStore");
        PKIX_NULLCHECK_TWO(params, store);

        PKIX_CHECK(PKIX_ProcessingParams_GetCertStores
                    (params, &certStores, plContext),
                    PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED);

        PKIX_CHECK(PKIX_List_AppendItem
                    (certStores, (PKIX_PL_Object *)store, plContext),
                    PKIX_LISTAPPENDITEMFAILED);

        PKIX_CHECK(PKIX_PL_Object_InvalidateCache
                    ((PKIX_PL_Object *)params, plContext),
                    PKIX_OBJECTINVALIDATECACHEFAILED);

cleanup:

        PKIX_DECREF(certStores);
        PKIX_RETURN(PROCESSINGPARAMS);
}
/*
 * FUNCTION: PKIX_RevocationChecker_CreateAndAddMethod
 */
PKIX_Error *
PKIX_RevocationChecker_CreateAndAddMethod(
    PKIX_RevocationChecker *revChecker,
    PKIX_ProcessingParams *params,
    PKIX_RevocationMethodType methodType,
    PKIX_UInt32 flags,
    PKIX_UInt32 priority,
    PKIX_PL_VerifyCallback verificationFn,
    PKIX_Boolean isLeafMethod,
    void *plContext)
{
    PKIX_List **methodList = NULL;
    PKIX_List  *unsortedList = NULL;
    PKIX_List  *certStores = NULL;
    pkix_RevocationMethod *method = NULL;
    pkix_LocalRevocationCheckFn *localRevChecker = NULL;
    pkix_ExternalRevocationCheckFn *externRevChecker = NULL;
    PKIX_UInt32 miFlags;
    
    PKIX_ENTER(REVOCATIONCHECKER, "PKIX_RevocationChecker_CreateAndAddMethod");
    PKIX_NULLCHECK_ONE(revChecker);

    /* If the caller has said "Either one is sufficient, then don't let the 
     * absence of any one method's info lead to an overall failure.
     */
    miFlags = isLeafMethod ? revChecker->leafMethodListFlags 
	                   : revChecker->chainMethodListFlags;
    if (miFlags & PKIX_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE)
	flags &= ~PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO;

    switch (methodType) {
    case PKIX_RevocationMethod_CRL:
        localRevChecker = pkix_CrlChecker_CheckLocal;
        externRevChecker = pkix_CrlChecker_CheckExternal;
        PKIX_CHECK(
            PKIX_ProcessingParams_GetCertStores(params, &certStores,
                                                plContext),
            PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED);
        PKIX_CHECK(
            pkix_CrlChecker_Create(methodType, flags, priority,
                                   localRevChecker, externRevChecker,
                                   certStores, verificationFn,
                                   &method,
                                   plContext),
            PKIX_COULDNOTCREATECRLCHECKEROBJECT);
        break;
    case PKIX_RevocationMethod_OCSP:
        localRevChecker = pkix_OcspChecker_CheckLocal;
        externRevChecker = pkix_OcspChecker_CheckExternal;
        PKIX_CHECK(
            pkix_OcspChecker_Create(methodType, flags, priority,
                                    localRevChecker, externRevChecker,
                                    verificationFn,
                                    &method,
                                    plContext),
            PKIX_COULDNOTCREATEOCSPCHECKEROBJECT);
        break;
    default:
        PKIX_ERROR(PKIX_INVALIDREVOCATIONMETHOD);
    }

    if (isLeafMethod) {
        methodList = &revChecker->leafMethodList;
    } else {
        methodList = &revChecker->chainMethodList;
    }
    
    if (*methodList == NULL) {
        PKIX_CHECK(
            PKIX_List_Create(methodList, plContext),
            PKIX_LISTCREATEFAILED);
    }
    unsortedList = *methodList;
    PKIX_CHECK(
        PKIX_List_AppendItem(unsortedList, (PKIX_PL_Object*)method, plContext),
        PKIX_LISTAPPENDITEMFAILED);
    PKIX_CHECK(
        pkix_List_BubbleSort(unsortedList, 
                             pkix_RevocationChecker_SortComparator,
                             methodList, plContext),
        PKIX_LISTBUBBLESORTFAILED);

cleanup:
    PKIX_DECREF(method);
    PKIX_DECREF(unsortedList);
    PKIX_DECREF(certStores);
    
    PKIX_RETURN(REVOCATIONCHECKER);
}
/*
 * FUNCTION: pkix_ProcessingParams_ToString
 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
 */
static PKIX_Error *
pkix_ProcessingParams_ToString(
        PKIX_PL_Object *object,
        PKIX_PL_String **pString,
        void *plContext)
{
        PKIX_ProcessingParams *procParams = NULL;
        char *asciiFormat = NULL;
        PKIX_PL_String *formatString = NULL;
        PKIX_PL_String *procParamsString = NULL;
        PKIX_PL_String *anchorsString = NULL;
        PKIX_PL_String *dateString = NULL;
        PKIX_PL_String *constraintsString = NULL;
        PKIX_PL_String *InitialPoliciesString = NULL;
        PKIX_PL_String *qualsRejectedString = NULL;
        PKIX_List *certStores = NULL;
        PKIX_PL_String *certStoresString = NULL;
        PKIX_PL_String *resourceLimitsString = NULL;

        PKIX_ENTER(PROCESSINGPARAMS, "pkix_ProcessingParams_ToString");
        PKIX_NULLCHECK_TWO(object, pString);

        PKIX_CHECK(pkix_CheckType
                    (object, PKIX_PROCESSINGPARAMS_TYPE, plContext),
                    PKIX_OBJECTNOTPROCESSINGPARAMS);

        asciiFormat =
                "[\n"
                "\tTrust Anchors: \n"
                "\t********BEGIN LIST OF TRUST ANCHORS********\n"
                "\t\t%s\n"
                "\t********END LIST OF TRUST ANCHORS********\n"
                "\tDate:    \t\t%s\n"
                "\tTarget Constraints:    %s\n"
                "\tInitial Policies:      %s\n"
                "\tQualifiers Rejected:   %s\n"
                "\tCert Stores:           %s\n"
                "\tResource Limits:       %s\n"
                "\tCRL Checking Enabled:  %d\n"
                "]\n";

        PKIX_CHECK(PKIX_PL_String_Create
                    (PKIX_ESCASCII,
                    asciiFormat,
                    0,
                    &formatString,
                    plContext),
                    PKIX_STRINGCREATEFAILED);

        procParams = (PKIX_ProcessingParams*)object;

        PKIX_TOSTRING(procParams->trustAnchors, &anchorsString, plContext,
                PKIX_OBJECTTOSTRINGFAILED);

        PKIX_TOSTRING(procParams->date, &dateString, plContext,
                PKIX_OBJECTTOSTRINGFAILED);

        PKIX_TOSTRING(procParams->constraints, &constraintsString, plContext,
                PKIX_OBJECTTOSTRINGFAILED);

        PKIX_TOSTRING
                (procParams->initialPolicies, &InitialPoliciesString, plContext,
                PKIX_OBJECTTOSTRINGFAILED);

        PKIX_CHECK(PKIX_PL_String_Create
                (PKIX_ESCASCII,
                (procParams->qualifiersRejected)?"TRUE":"FALSE",
                0,
                &qualsRejectedString,
                plContext),
                PKIX_STRINGCREATEFAILED);

        /* There is no ToString function for CertChainCheckers */

       PKIX_CHECK(PKIX_ProcessingParams_GetCertStores
                (procParams, &certStores, plContext),
                PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED);

        PKIX_TOSTRING(certStores, &certStoresString, plContext,
                PKIX_LISTTOSTRINGFAILED);

        PKIX_TOSTRING(procParams->resourceLimits,
                &resourceLimitsString,
                plContext,
                PKIX_OBJECTTOSTRINGFAILED);

        PKIX_CHECK(PKIX_PL_Sprintf
                (&procParamsString,
                plContext,
                formatString,
                anchorsString,
                dateString,
                constraintsString,
                InitialPoliciesString,
                qualsRejectedString,
                certStoresString,
                resourceLimitsString,
                procParams->isCrlRevocationCheckingEnabled,
                procParams->isCrlRevocationCheckingEnabledWithNISTPolicy),
                PKIX_SPRINTFFAILED);

        *pString = procParamsString;

cleanup:

        PKIX_DECREF(formatString);
        PKIX_DECREF(anchorsString);
        PKIX_DECREF(dateString);
        PKIX_DECREF(constraintsString);
        PKIX_DECREF(InitialPoliciesString);
        PKIX_DECREF(qualsRejectedString);
        PKIX_DECREF(certStores);
        PKIX_DECREF(certStoresString);
        PKIX_DECREF(resourceLimitsString);

        PKIX_RETURN(PROCESSINGPARAMS);
}