//
//  DBOperation.m
//  zhuxun
//
//  Created by winsoft on 17/4/24.
//
//

#import "DBOperation.h"
#import <FMDB/FMDB.h>
#import "DBConfigureCenter.h"
#import <MJExtension/MJExtension.h>
//static FMDatabaseQueue *dbqueue;
@interface DBOperation()
@property (nonatomic , strong) FMDatabaseQueue *dbqueue;

@end

@implementation DBOperation
+ (instancetype)dbOperationWithPath:(NSString *)path
{
    DBOperation *dbOperation = [[DBOperation alloc]init];
    
    if (!dbOperation.dbqueue) {
        dbOperation.dbqueue = [FMDatabaseQueue databaseQueueWithPath:path];
    }
    
    return dbOperation;
    
}

- (void)creatDBbySQL:(NSString *)sql Path:(NSString *)path
{
    
    [self.dbqueue inDatabase:^(FMDatabase *db) {
        [db executeUpdate:sql];
        
    }];
    
    
    
    //dbqueue = [FMDatabaseQueue databaseQueueWithPath:path];
    //    if (dbqueue == nil) {
    //        dbqueue = [FMDatabaseQueue databaseQueueWithPath:path];
    //    }
    //
    //    [dbqueue inDatabase:^(FMDatabase *db) {
    //        [db executeUpdate:sql];
    //
    //    }];
    
}

- (void)creatDBWithTableName:(NSString *)tableName dbModelClass:(Class)dbModelClass Path:(NSString *)path autoUpgrade:(BOOL)autoUpgrade uniqueCloumName:(NSString *)uniqueCloumName
{
    NSString *sql = [DBConfigureCenter getDBTableWithTableName:tableName className:dbModelClass];
    
    [self creatDBbySQL:sql Path:path];
    
    //自动升级.
    if (autoUpgrade) {
        
        [self judgeCloumExistAndAutoUpdateWithTableName:tableName allCloumnName_TypeArray:[DBConfigureCenter sqlCloumnCheckWithClassName:dbModelClass]];
    }
    
    if (uniqueCloumName.length) {
        NSString *indexSql = [NSString stringWithFormat:@"create unique index %@_index_%@ on %@(%@)",tableName,uniqueCloumName,tableName,uniqueCloumName];
        
        [self addDataToDBWithSQL:indexSql];
    }
}

//自动升级.
- (void)judgeCloumExistAndAutoUpdateWithTableName:(NSString *)tableName allCloumnName_TypeArray:(NSArray<DBStructModel *> *)allCloumnName_TypeArray
{
    
    NSString *sql = [NSString stringWithFormat:@"pragma table_info (%@)",tableName];
    
    __weak typeof(self)weakself = self;
    
    [self quaryDBbySQL:sql result:^(NSMutableArray *array) {
        
        NSArray *dbStructArray = [DBStructModel mj_objectArrayWithKeyValuesArray:array];
        
        
        for (DBStructModel *dbModel in allCloumnName_TypeArray) {
            
            NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name = %@",dbModel.name];
            
            //如果name在数据库返回的字段内找不到,则插入.
            NSArray *targetKeyArray = [dbStructArray filteredArrayUsingPredicate:predicate];
            
            if (!targetKeyArray.count) {
                
                NSString *alertStr = [NSString stringWithFormat:@"ALTER TABLE %@ ADD %@ %@",tableName,dbModel.name,dbModel.type];
                
                [weakself addDataToDBWithSQL:alertStr];
                
            }
        }
        
    }];
}


//查询目标群组
- (void)quaryDBbySQL:(NSString *)sql result:(void(^)(NSMutableArray *array))result
{
    __block FMResultSet *rs = nil;
    NSMutableArray *tempArray = [NSMutableArray array];
    [self.dbqueue inDatabase:^(FMDatabase *db) {
        
        
        rs = [db executeQuery:sql];
        
        while (rs.next) {
            //获取nsdata
            //            NSData *data = rs.resultDictionary ;//[rs dataForColumn:nil];
            //            //将nsdata转成weibostatusmodel
            //            GroupObject *groupObject = [NSKeyedUnarchiver unarchiveObjectWithData:data];
            //            [tempArray addObject:groupObject];
            NSDictionary *dict = rs.resultDictionary;
            [tempArray addObject:dict];
            
        }
    }];
    
    if (tempArray.count) {
        result(tempArray);
    }else result (nil);
    
}

//插入模型
- (void)addDataDBWithTableName:(NSString *)tableName model:(id)model
{
    NSString *sql = [self getInsertModelSqlWithTableName:tableName model:model];
    [self addDataToDBWithSQL:sql];
}

- (void)addDatasDBWithTableName:(NSString *)tableName models:(NSArray *)models
{
    NSMutableArray *tempSqlsArray = [NSMutableArray array];
    
    for (id model in models) {
        [tempSqlsArray addObject:[self getInsertModelSqlWithTableName:tableName model:model]];
    }
    
    [self addDatasToDBWithSQLs:tempSqlsArray];
    
}

- (void)addDataToDBWithSQL:(NSString *)sql
{
    [self.dbqueue inDatabase:^(FMDatabase *db) {
        [db executeUpdate:sql];
    }];
}

- (void)addDatasToDBWithSQLs:(NSArray *)sqls
{
    [self.dbqueue inDatabase:^(FMDatabase *db) {
        
#ifdef DEBUG
        db.logsErrors = YES;
#else
        db.logsErrors = NO;
#endif
        
        NSLog(@"start1111111111");
        
        
        [db beginTransaction];
        @try {
            for (NSString *sql in sqls) {
                [db executeUpdate:sql];
            }
            
            
        }
        @catch (NSException *exception)
        {
            [db rollback];
        }
        @finally
        {
            [db commit];
        }
        
        
        NSLog(@"end1111111111");
        
    }];
}

- (NSString *)getInsertModelSqlWithTableName:(NSString *)tableName model:(id)model
{
    Class cls = [model class];
    
    unsigned int ivarsCnt = 0;
    //　获取类成员变量列表，ivarsCnt为类成员数量
    Ivar *ivars = class_copyIvarList(cls, &ivarsCnt);
    
    //　遍历成员变量列表，其中每个变量都是Ivar类型的结构体
    int i = 0;
    NSMutableArray *keys = [NSMutableArray array];
    NSMutableArray *values = [NSMutableArray array];
    //    NSMutableArray *valueSqlSymbol = [NSMutableArray array];
    for (const Ivar *p = ivars; p < ivars + ivarsCnt; ++p)
    {
        
        Ivar const ivar = *p;
        
        //　获取变量名
        NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
        // 若此变量未在类结构体中声明而只声明为Property，则变量名加前缀 '_'下划线
        // 比如 @property(retain) NSString *abc;则 key == _abc;
        
        //　获取变量值
        id value = [model valueForKey:key];
        //        id value = [self valueForKey:key];
        
        //　取得变量类型
        // 通过 type[0]可以判断其具体的内置类型
        //        const char *type = ivar_getTypeEncoding(ivar);
        
        if(value)
        {
            BOOL strValue = NO;
            if ([value isKindOfClass:[NSString class]]) {
                strValue = YES;
                NSString *strValue = value;
                if (!strValue.length) {
                    continue;
                }
            }
            
            [keys addObject:[key substringFromIndex:1]];
            
            //字符串需要新增一个'',如果是字典对象呢?
            if (strValue) {
                [values addObject:[NSString stringWithFormat:@"'%@'",value]];
            }else [values addObject:value];
            
            //            [valueSqlSymbol addObject:@"?"];
        }
        
        i++;
    }
    
    free(ivars);
    
    NSString *fileKeyListStr = [keys componentsJoinedByString:@","];
    NSString *fileValueListStr = [values componentsJoinedByString:@","];
    
    NSString *SQL = [NSString stringWithFormat:@"insert into %@ (%@) values(%@)",tableName,fileKeyListStr,fileValueListStr];
    return SQL;
}
@end
