/* Copyright Airship and Contributors */

#import <Foundation/Foundation.h>
#import "UAJSONMatcher.h"
#import "UAJSONValueMatcher.h"

NS_ASSUME_NONNULL_BEGIN

/**
 * Represents the possible error conditions when deserializing predicate from JSON.
 */
typedef NS_ENUM(NSInteger, UAJSONPredicateErrorCode) {
    /**
     * Indicates an error with the predicate JSON definition.
     */
    UAJSONPredicateErrorCodeInvalidJSON,
};

/**
 * The domain for NSErrors generated by `predicateWithJSON:error`.
 */
extern NSString * const UAJSONPredicateErrorDomain;


/**
 * Predicate for JSON payloads.
 */
@interface UAJSONPredicate : NSObject

///---------------------------------------------------------------------------------------
/// @name JSON Predicate Properties
///---------------------------------------------------------------------------------------

/**
 * The predicate's JSON payload.
 */
@property(nonatomic, readonly) NSDictionary *payload;

///---------------------------------------------------------------------------------------
/// @name JSON Predicate Factories
///---------------------------------------------------------------------------------------

/**
 * Factory method to create a JSON predicate from a UAJSONMatcher.
 *
 * @param matcher A JSON matcher.
 * @return A JSON predicate.
 */
+ (instancetype)predicateWithJSONMatcher:(UAJSONMatcher *)matcher;

/**
 * Factory method to create a JSON predicate formed by AND-ing an array of predicates.
 *
 * @param subpredicates An array of predicates.
 * @return A JSON predicate.
 */
+ (instancetype)andPredicateWithSubpredicates:(NSArray<UAJSONPredicate*>*)subpredicates;


/**
 * Factory method to create a JSON predicate formed by OR-ing an array of predicates.
 *
 * @param subpredicates An array of predicates.
 * @return A JSON predicate.
 */
+ (instancetype)orPredicateWithSubpredicates:(NSArray<UAJSONPredicate*>*)subpredicates;

/**
 * Factory method to create a JSON predicate by NOT-ing a predicate.
 *
 * @param subpredicate A predicate.
 * @return A JSON predicate.
 */
+ (instancetype)notPredicateWithSubpredicate:(UAJSONPredicate *)subpredicate;

/**
 * Factory method to create a predicate from a JSON payload.
 *
 * @param json The JSON payload.
 * @param error An NSError pointer for storing errors, if applicable.
 * @return A predicate or `nil` if the JSON is invalid.
 */
+ (nullable instancetype)predicateWithJSON:(id)json error:(NSError * _Nullable *)error;

///---------------------------------------------------------------------------------------
/// @name JSON Predicate Evaluation
///---------------------------------------------------------------------------------------

/**
 * Evaluates the object with the predicate.
 *
 * @param object The object to evaluate.
 * @return `YES` if the predicate matches the object, otherwise `NO`.
 */
- (BOOL)evaluateObject:(nullable id)object;



@end

NS_ASSUME_NONNULL_END
