//
//  NSObject+ZYJMJKeyValue.h
//  ZYJMJExtension
//
//  Created by mj on 13-8-24.
//  Copyright (c) 2013年 小码哥. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "ZYJMJExtensionConst.h"
#import <CoreData/CoreData.h>
#import "ZYJMJProperty.h"

/**
 *  KeyValue协议
 */
@protocol ZYJMJKeyValue <NSObject>
@optional
/**
 *  只有这个数组中的属性名才允许进行字典和模型的转换
 */
+ (NSArray *)mj_ZYJallowedPropertyNames;

/**
 *  这个数组中的属性名将会被忽略：不进行字典和模型的转换
 */
+ (NSArray *)mj_ZYJignoredPropertyNames;

/**
 *  将属性名换为其他key去字典中取值
 *
 *  @return 字典中的key是属性名，value是从字典中取值用的key
 */
+ (NSDictionary *)mj_ZYJreplacedKeyFromPropertyName;

/**
 *  将属性名换为其他key去字典中取值
 *
 *  @return 从字典中取值用的key
 */
+ (id)mj_ZYJreplacedKeyFromPropertyName121:(NSString *)propertyName;

/**
 *  数组中需要转换的模型类
 *
 *  @return 字典中的key是数组属性名，value是数组中存放模型的Class（Class类型或者NSString类型）
 */
+ (NSDictionary *)mj_ZYJobjectClassInArray;

/**
 *  旧值换新值，用于过滤字典中的值
 *
 *  @param oldValue 旧值
 *
 *  @return 新值
 */
- (id)mj_ZYJnewValueFromOldValue:(id)oldValue property:(ZYJMJProperty *)property;

/**
 *  当字典转模型完毕时调用
 */
- (void)mj_ZYJkeyValuesDidFinishConvertingToObject;

/**
 *  当模型转字典完毕时调用
 */
- (void)mj_ZYJobjectDidFinishConvertingToKeyValues;
@end

@interface NSObject (ZYJMJKeyValue) <ZYJMJKeyValue>
#pragma mark - 类方法
/**
 * 字典转模型过程中遇到的错误
 */
+ (NSError *)mj_ZYJerror;

/**
 *  模型转字典时，字典的key是否参考replacedKeyFromPropertyName等方法（父类设置了，子类也会继承下来）
 */
+ (void)mj_ZYJreferenceReplacedKeyWhenCreatingKeyValues:(BOOL)reference;

#pragma mark - 对象方法
/**
 *  将字典的键值对转成模型属性
 *  @param keyValues 字典(可以是NSDictionary、NSData、NSString)
 */
- (instancetype)mj_ZYJsetKeyValues:(id)keyValues;

/**
 *  将字典的键值对转成模型属性
 *  @param keyValues 字典(可以是NSDictionary、NSData、NSString)
 *  @param context   CoreData上下文
 */
- (instancetype)mj_ZYJsetKeyValues:(id)keyValues context:(NSManagedObjectContext *)context;

/**
 *  将模型转成字典
 *  @return 字典
 */
- (NSMutableDictionary *)mj_ZYJkeyValues;
- (NSMutableDictionary *)mj_ZYJkeyValuesWithKeys:(NSArray *)keys;
- (NSMutableDictionary *)mj_ZYJkeyValuesWithIgnoredKeys:(NSArray *)ignoredKeys;

/**
 *  通过模型数组来创建一个字典数组
 *  @param objectArray 模型数组
 *  @return 字典数组
 */
+ (NSMutableArray *)mj_ZYJkeyValuesArrayWithObjectArray:(NSArray *)objectArray;
+ (NSMutableArray *)mj_ZYJkeyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys;
+ (NSMutableArray *)mj_ZYJkeyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys;

#pragma mark - 字典转模型
/**
 *  通过字典来创建一个模型
 *  @param keyValues 字典(可以是NSDictionary、NSData、NSString)
 *  @return 新建的对象
 */
+ (instancetype)mj_ZYJobjectWithKeyValues:(id)keyValues;

/**
 *  通过字典来创建一个CoreData模型
 *  @param keyValues 字典(可以是NSDictionary、NSData、NSString)
 *  @param context   CoreData上下文
 *  @return 新建的对象
 */
+ (instancetype)mj_ZYJobjectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context;

/**
 *  通过plist来创建一个模型
 *  @param filename 文件名(仅限于mainBundle中的文件)
 *  @return 新建的对象
 */
+ (instancetype)mj_ZYJobjectWithFilename:(NSString *)filename;

/**
 *  通过plist来创建一个模型
 *  @param file 文件全路径
 *  @return 新建的对象
 */
+ (instancetype)mj_ZYJobjectWithFile:(NSString *)file;

#pragma mark - 字典数组转模型数组
/**
 *  通过字典数组来创建一个模型数组
 *  @param keyValuesArray 字典数组(可以是NSDictionary、NSData、NSString)
 *  @return 模型数组
 */
+ (NSMutableArray *)mj_ZYJobjectArrayWithKeyValuesArray:(id)keyValuesArray;

/**
 *  通过字典数组来创建一个模型数组
 *  @param keyValuesArray 字典数组(可以是NSDictionary、NSData、NSString)
 *  @param context        CoreData上下文
 *  @return 模型数组
 */
+ (NSMutableArray *)mj_ZYJobjectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context;

/**
 *  通过plist来创建一个模型数组
 *  @param filename 文件名(仅限于mainBundle中的文件)
 *  @return 模型数组
 */
+ (NSMutableArray *)mj_ZYJobjectArrayWithFilename:(NSString *)filename;

/**
 *  通过plist来创建一个模型数组
 *  @param file 文件全路径
 *  @return 模型数组
 */
+ (NSMutableArray *)mj_ZYJobjectArrayWithFile:(NSString *)file;

#pragma mark - 转换为JSON
/**
 *  转换为JSON Data
 */
- (NSData *)mj_ZYJJSONData;
/**
 *  转换为字典或者数组
 */
- (id)mj_ZYJJSONObject;
/**
 *  转换为JSON 字符串
 */
- (NSString *)mj_ZYJJSONString;
@end

@interface NSObject (ZYJMJKeyValueDeprecated_v_2_5_16)
- (instancetype)setKeyValues:(id)keyValue ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
- (instancetype)setKeyValues:(id)keyValues error:(NSError **)error ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
- (instancetype)setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
- (instancetype)setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context error:(NSError **)error ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (void)referenceReplacedKeyWhenCreatingKeyValues:(BOOL)reference ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
- (NSMutableDictionary *)keyValues ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
- (NSMutableDictionary *)keyValuesWithError:(NSError **)error ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
- (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
- (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys error:(NSError **)error ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
- (NSMutableDictionary *)keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
- (NSMutableDictionary *)keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys error:(NSError **)error ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray error:(NSError **)error ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys error:(NSError **)error ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys error:(NSError **)error ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (instancetype)objectWithKeyValues:(id)keyValues ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (instancetype)objectWithKeyValues:(id)keyValues error:(NSError **)error ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (instancetype)objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (instancetype)objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context error:(NSError **)error ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (instancetype)objectWithFilename:(NSString *)filename ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (instancetype)objectWithFilename:(NSString *)filename error:(NSError **)error ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (instancetype)objectWithFile:(NSString *)file ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (instancetype)objectWithFile:(NSString *)file error:(NSError **)error ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray error:(NSError **)error ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context error:(NSError **)error ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (NSMutableArray *)objectArrayWithFilename:(NSString *)filename ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (NSMutableArray *)objectArrayWithFilename:(NSString *)filename error:(NSError **)error ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (NSMutableArray *)objectArrayWithFile:(NSString *)file ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
+ (NSMutableArray *)objectArrayWithFile:(NSString *)file error:(NSError **)error ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
- (NSData *)JSONData ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
- (id)JSONObject ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
- (NSString *)JSONString ZYJMJExtensionDeprecated("请在方法名前面加上mj_ZYJ前缀，使用mj_ZYJ***");
@end
