// // RulesDetailViewController.m // kneet2 // // Created by Jason Lee on 11/30/15. // Copyright © 2015 ntels. All rights reserved. // #import "JDObject.h" #import "RequestHandler.h" #import "RuleModel.h" #import "CustomTableView.h" #import "CustomLabel.h" #import "CustomButton.h" #import "CustomImageView.h" #import "UIImageView+WebCache.h" #import "RulesDetailViewController.h" #import "RulesConditionViewController.h" #import "DeviceModel.h" #import "RulesAddViewController.h" @implementation RulesDetailTitleTableViewCell @end @implementation RulesDetailHeaderTableViewCell @end @implementation RulesDetailTableViewCell @end @implementation RulesDetailPushTableViewCell @end @implementation RulesDetailConditionHeaderTableViewCell @end @implementation RulesDetailConditionTableViewCell @end @implementation RulesDetailExecutionTableViewCell @end @implementation RulesDetailFooterTableViewCell @end @interface RulesDetailViewController () { RuleDetailModel *_ruleDetail; NSMutableArray *_triggers, *_actions, *_conditions; NSMutableArray *_arrayForHeader, *_arrayForFooter; RulesConditionViewController *_rcv; NSInteger _sectionCount; BOOL _hasDeviceAction, _hasPushAction, _hasCondition; //요일 조건 외의 조건 CustomButton *_btnUseRule; UIImage *_btnImageRun, *_btnImageStop; } @end #pragma mark - Class Definition @implementation RulesDetailViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. [self initProperties]; [self initUI]; [self prepareViewDidLoad]; } - (void)initProperties { _arrayForHeader = [[NSMutableArray alloc] init]; _arrayForFooter = [[NSMutableArray alloc] init]; } - (void)initUI { if (![JDFacade facade].loginUser.isHomehubOnline) { _lblTitle.text = @"홈허브 오프라인"; [_lblTitle setColor:kUITextColor02 text:_lblTitle.text]; } [self initTableViewAsDefaultStyle:_tableView]; [self setThingsPopoverOptions]; _btnImageRun = [UIImage imageNamed:@"img_rule_list_playbtn_active"]; _btnImageStop = [UIImage imageNamed:@"img_rule_list_playbtn_disable"]; } - (void)prepareViewDidLoad { [self requestRuleDetail]; } - (void)setThingsPopoverOptions { //set Popover Contents __weak typeof(self) weakSelf = self; _popooverOptionArray = [[NSMutableArray alloc] init]; [_popooverOptionArray addObject:@{@"menuName" : NSLocalizedString(@"새로고침",nil), @"iconName": @"img_bg_morepopup_icon_refresh", @"target": weakSelf, @"selector": [NSValue valueWithPointer:@selector(requestRuleDetail)]}]; if ([JDFacade facade].loginUser.level > 10) {//파워유저 이상일 경우, [_popooverOptionArray addObject:@{@"menuName" : NSLocalizedString(@"편집", @"편집"), @"iconName": @"img_bg_morepopup_icon_edit", @"target": weakSelf, @"selector": [NSValue valueWithPointer:@selector(editRule)]}]; [_popooverOptionArray addObject:@{@"menuName" : NSLocalizedString(@"삭제", @"삭제"), @"iconName": @"img_bg_morepopup_icon_del", @"target": weakSelf, @"selector": [NSValue valueWithPointer:@selector(deleteRule)]}]; } } - (void)editRule { RulesAddViewController *vc = (RulesAddViewController *)[CommonUtil instantiateViewControllerWithIdentifier:@"RulesAddViewController" storyboardName:@"Rules"]; vc.refRuleDetail = _ruleDetail; [self presentViewController:vc animated:YES completion:nil]; } - (void)deleteRule { [[JDFacade facade] confirmTitle:@"규칙 삭제" message:@"규칙을 삭제하시겠습니까?" completion:^(CustomAlertView *alertView, NSInteger buttonIndex) { if (buttonIndex == 0) {//OK [self requestDeleteRule]; } }]; } #pragma mark - Main Logic - (void)requestRuleDetail { NSString *path = [NSString stringWithFormat:API_GET_RULE_DETAIL, _refRule.homegrpRuleId]; [[RequestHandler handler] sendAsyncGetRequestAPIPath:path parameters:nil modelClass:[RuleDetailModel class] completion:^(id responseObject) { if (!responseObject) {//응답결과가 잘못되었거나 없을 경우, return; } _ruleDetail = (RuleDetailModel *) responseObject; if (_ruleDetail) {//API 성공 , [self setContents]; } } failure:^(id errorObject) { JDErrorModel *error = (JDErrorModel *)errorObject; [[JDFacade facade] alert:error.errorMessage]; }]; } - (void)setDeviceValue:(NSMutableArray *)items { NSArray *matchedArray = [_triggers filteredArrayUsingPredicateFormat:@"itemTypeCode == %@", ksItemSubTypeCodeDevice]; for (ItemModel *item in matchedArray) {//device items for (ItemSubModel *subItem in item.subItems) { [[JDFacade facade] setRadioButtonStatus:@YES object:subItem]; [[JDFacade facade] setCheckBoxStatus:@YES object:subItem]; } } } - (void)setContents { _triggers = (NSMutableArray *)[[NSMutableArray alloc] initWithArray:_ruleDetail.triggers]; _actions = (NSMutableArray *)[[NSMutableArray alloc] initWithArray:_ruleDetail.actions]; _conditions = (NSMutableArray *)[[NSMutableArray alloc] initWithArray:_ruleDetail.conditions]; [self setDeviceValue:_triggers]; [self setDeviceValue:_actions]; [self setDeviceValue:_conditions]; //check elements _hasDeviceAction = [_actions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeDevice] != nil; _hasPushAction = [_actions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeAppPush] != nil; _hasCondition = [_conditions objectKey:@"itemSubTypeCode" eqaulToString:ksConditionSubTypeCodeHomeMode] != nil; _hasCondition = [_conditions objectKey:@"itemSubTypeCode" eqaulToString:ksConditionSubTypeCodeDueDate] ? YES : _hasCondition; _hasCondition = [_conditions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeDevice] ? YES : _hasCondition; [_tableView reloadData]; } - (void)requestDeleteRule { NSString *path = [NSString stringWithFormat:API_DELETE_RULE, _ruleDetail.homegrpRuleId]; [[RequestHandler handler] sendAsyncRequestAPIPath:path method:ksHTTPRequestDELETE parameters:nil modelClass:[JDJSONModel class] showLoadingView:YES completion:^(id responseObject) { [[JDFacade facade] dismissModalStack:YES completion:^{ [[JDFacade facade] toast:NSLocalizedString(@"삭제되었습니다", @"삭제되었습니다")]; }]; } failure:^(id errorObject) { JDErrorModel *error = (JDErrorModel *)errorObject; [[JDFacade facade] alert:error.errorMessage]; }]; } - (void)requestChangeRuleStatus { //parameters NSDictionary *parameter = @{@"status_code" : [_ruleDetail.useYn boolValue] ? @"03" : @"02"}; NSString *path = [NSString stringWithFormat:API_POST_RULE_STATUS, _ruleDetail.homegrpRuleId]; [[RequestHandler handler] sendAsyncPostRequestAPIPath:path parameters:parameter modelClass:[JDJSONModel class] completion:^(id responseObject) { _ruleDetail.useYn = [_ruleDetail.useYn boolValue] ? ksNO : ksYES; //toggle if ([_ruleDetail.useYn boolValue]) { [[JDFacade facade] toast:@"규칙을 다시 시작합니다"]; } else { [[JDFacade facade] toast:@"규칙을 중단합니다"]; } [_tableView reloadData]; } failure:^(id errorObject) { JDErrorModel *error = (JDErrorModel *)errorObject; [[JDFacade facade] alert:error.errorMessage]; }]; } #pragma mark - UITableView DataSource & Delegate - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 6; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { NSInteger count = 0; if (section == 0 || section == 5) {//title count = 1; } else if (section == 1) {//triggers count = _triggers && _triggers.count ? _triggers.count : 0; } else if (section == 2) {//actions ItemModel *deviceItem = [_actions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeDevice]; count = deviceItem.subItems && deviceItem.subItems.count ? deviceItem.subItems.count : 0; } else if (section == 3) { count = _hasPushAction; } else if (section == 4) { count = _hasCondition; } return count; } - (NSString *)headerTitleForSection:(NSInteger)section { NSString *title = nil; if (section == 1) {//trigger title = @"이 때가 되면"; if (_triggers && _triggers.count) { ItemModel *item = _triggers[0]; if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeDevice]) { title = @"장치 상태가 바뀔 때"; } else if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeTimer]) { title = @"이 시간마다"; } else if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeHeat]) { title = @"더울때 / 추울때"; } else if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeDaylight]) { title = @"해뜰때 / 질때"; } } } else if (section == 2) {//action title = @"이 장치를 실행"; } else if (section == 3) {//pushes title = @"알림 메시지"; } return title; } - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { UIView *view = _arrayForHeader.count > section ? _arrayForHeader[section] : nil; if (!view) { if (section == 0 || section == 5) {//title view = [[UIView alloc] init]; } else if (section == 1 || section == 2 || section == 3) { RulesDetailHeaderTableViewCell *hcell = (RulesDetailHeaderTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"HeaderCellIdentifier"]; hcell.width = IPHONE_WIDTH; view = [[UIView alloc] initWithFrame:hcell.contentView.frame]; [view addSubview:hcell]; hcell.lblTitle.text = [self headerTitleForSection:section]; } else if (section == 4) {//conditions RulesDetailConditionHeaderTableViewCell *hcell = (RulesDetailConditionHeaderTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"ConditionHeaderCellIdentifier"]; hcell.width = IPHONE_WIDTH; view = [[UIView alloc] initWithFrame:hcell.contentView.frame]; [view addSubview:hcell]; } if (_arrayForHeader.count == section) { [_arrayForHeader insertObject:view atIndex:section]; } } else { if ((section == 2 && !_hasDeviceAction) || (section == 3 && !_hasPushAction) || (section == 4 && !_hasCondition)) { view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, IPHONE_WIDTH, CGFLOAT_MIN)]; } else if (section == 1 || section == 2 || section == 3) { RulesDetailHeaderTableViewCell *hcell = (RulesDetailHeaderTableViewCell *)view.subviews[0]; hcell.lblTitle.text = hcell.lblTitle.text = [self headerTitleForSection:section]; } } return view; } - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { CGFloat height = 75.0f; if (section == 0 || section == 5) { height = CGFLOAT_MIN; } else if (section == 2) { height = _hasDeviceAction ? 75.0f : CGFLOAT_MIN; } else if (section == 3) { height = _hasPushAction ? 75.0f : CGFLOAT_MIN; } else if (section == 4) { height = _hasCondition ? 75.0f : CGFLOAT_MIN; } return height; } - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { UIView *view = _arrayForFooter.count > section ? _arrayForFooter[section] : nil; if (!view) { RulesDetailFooterTableViewCell *hcell = (RulesDetailFooterTableViewCell *)[tableView dequeueReusableCellWithIdentifier:@"FooterCellIdentifier"]; hcell.width = IPHONE_WIDTH; if (section == 4) { hcell.topLine.hidden = YES; } view = [[UIView alloc] initWithFrame:hcell.contentView.frame]; [view addSubview:hcell]; if (_arrayForHeader.count == section) { [_arrayForHeader insertObject:view atIndex:section]; } } return view; } - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { CGFloat height = 15.0f; if (section == 0 || section == 5) { height = CGFLOAT_MIN; } else if (section == 2) { height = _hasDeviceAction ? 15.0f : CGFLOAT_MIN; } else if (section == 3) { height = _hasPushAction ? 15.0f : CGFLOAT_MIN; } else if (section == 4) { height = _hasCondition ? 15.0f : CGFLOAT_MIN; } return height; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { CGFloat height = 0.0f; NSInteger section = indexPath.section; if (section == 0) {//title height = 56; } else if (section == 1) {//triggers height = 86; } else if (section == 2) {//actions height = 86; } else if (section == 3) {//push-message ItemModel *pushItem = [_actions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeAppPush]; ItemSubModel *push = pushItem.subItems[0]; CGFloat width = IPHONE_WIDTH - 85; CustomLabel *lblTemp = [[CustomLabel alloc] initWithFrame:CGRectMake(0, 0, width, 18)]; lblTemp.font = [UIFont systemFontOfSize:kUIFontSize02]; lblTemp.numberOfLines = 0; CGFloat adjustHeight = [CommonUtil getSizeFromString:push.cmdclsValue font:lblTemp.font width:width].height; adjustHeight = adjustHeight < 18 ? 0 : adjustHeight - 18; height = 61 + adjustHeight; } else if (section == 4) {//conditions if (!_rcv) { _rcv = [CommonUtil instantiateViewControllerWithIdentifier:@"RulesConditionViewController" storyboardName:@"Rules"]; [self addChildViewController:_rcv]; [_rcv didMoveToParentViewController:self]; } height = _rcv.tableHeight; } else if (section == 5) {//execution height = [JDFacade facade].loginUser.level == 90 ? 190.0f: 190.0f - 75.0f; //마스터만 규칙 실행 여부를 설정 가능함. } return height; } - (void)configureTriggerCell:(RulesDetailTableViewCell *)cell item:(ItemModel *)item { ItemSubModel *subItem = nil; if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeDevice]) {//장치일 경우 subItem = [item.subItems matchedObjectName:ksCustomRadioButtonStatus condition:YES]; cell.lblItem.text = subItem.sourceName; if ([subItem.deleteYn boolValue]) { [cell.lblItem setStrikethrough:cell.lblItem.text]; } cell.lblSubItem.text = subItem.sourceSubName; //노드의 액션 값을 세팅함. if (subItem.cmdclsValueList && subItem.cmdclsValueList.count) {//커맨드클래스 밸루 리스트가 있을 경우, CmdClsValueModel *cmdclsValue = [subItem.cmdclsValueList matchedObjectName:ksCustomRadioButtonStatus condition:YES]; cell.lblCondition.text = [DeviceModel contentValueMsgByCmdClsCode:subItem.cmdclsCode cmdclsTypeId:(NSString *)subItem.cmdclsTypeId contentValue:cmdclsValue.cmdclsValue]; } else { if (subItem.cmdclsValueMsg) { cell.lblCondition.text = subItem.cmdclsValueMsg; } else { NSString *condition = [subItem.conditionTypeCode isEqualToString:ksConditionTypeCodeGreatOrEqual] ? @"이상" : @"이하"; cell.lblCondition.text = [NSString stringWithFormat:@"%@%@ %@", subItem.cmdclsValue, subItem.unit, condition]; } } cell.lblCondition.hidden = NO; } else if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeTimer]) { subItem = item.subItems && item.subItems.count ? item.subItems[0] : nil; if (subItem) { NSInteger phour = [subItem.hour integerValue]; NSString *period = phour < 12 ? @"AM" : @"PM";//NSLocalizedString(@"오전", @"오전") : NSLocalizedString(@"오후", @"오후"); if ([period isEqualToString:@"PM"]) { if (phour > 12) { phour -= 12; } } NSString *title = [NSString stringWithFormat:@"%@ %zd:%@", period, phour, subItem.minute]; // NSDictionary *titleColor = @{NSForegroundColorAttributeName : kUITextColor02}; cell.lblItem.text = title; cell.lblSubItem.text = [self daysOfWeekAtSubItem]; cell.lblCondition.hidden = YES; } } else if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeDaylight]) { subItem = item.subItems && item.subItems.count ? item.subItems[0] : nil; if (subItem) { NSString *title = [subItem.sourceSubId isEqualToString:@"sunriseUtcTime"] ? @"해뜰때" : @"해질때"; cell.lblItem.text = title; cell.lblSubItem.text = [NSString stringWithFormat:@"%@ / %@", subItem.sourceName, [self daysOfWeekAtSubItem]]; cell.lblCondition.hidden = YES; } } else if ([item.itemSubTypeCode isEqualToString:ksItemSubTypeCodeHeat]) { subItem = item.subItems && item.subItems.count ? item.subItems[0] : nil; if (subItem) { NSString *title = [subItem.conditionTypeCode isEqualToString:ksConditionTypeCodeGreatOrEqual] ? @"더울때" : @"추울때"; cell.lblItem.text = title; cell.lblSubItem.text = [NSString stringWithFormat:@"%@ / %@℃ / %@", subItem.sourceName, subItem.cmdclsValue, [self daysOfWeekAtSubItem]]; cell.lblCondition.hidden = YES; } } [cell.imgvIcon sd_setImageWithURL:[NSURL URLWithString:subItem.imageFileName] placeholderImage:nil options:SDWebImageRefreshCached]; } - (NSString *)daysOfWeekAtSubItem { NSString *daysOfWeek = ksEmptyString; ItemModel *daysCondition = [_conditions objectKey:@"itemSubTypeCode" eqaulToString:ksConditionSubTypeCodeDaysOfWeek]; if (daysCondition) { ItemSubModel *subCondition = daysCondition.subItems[0]; daysOfWeek = subCondition.daysOfWeek; } return daysOfWeek; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSInteger section = indexPath.section; UITableViewCell *cell = nil; if (section == 0) {//title RulesDetailTitleTableViewCell *tcell = (RulesDetailTitleTableViewCell *)[_tableView dequeueReusableCellWithIdentifier:@"TitleCellIdentifier"]; tcell.lblRuleTitle.text = _ruleDetail.ruleName; cell = tcell; } else if (section == 1) {//triggers ItemModel *item = _triggers[indexPath.row]; RulesDetailTableViewCell *tcell = (RulesDetailTableViewCell *)[_tableView dequeueReusableCellWithIdentifier:@"RulesCellIdentifier"]; [self configureTriggerCell:tcell item:item]; tcell.lblItem.textColor = kUITextColor02; cell = tcell; } else if (section == 2) {//actions - 장치일 경우, ItemModel *deviceItem = [_actions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeDevice]; ItemSubModel *subItem = deviceItem.subItems[indexPath.row]; RulesDetailTableViewCell *tcell = (RulesDetailTableViewCell *)[_tableView dequeueReusableCellWithIdentifier:@"RulesCellIdentifier"]; tcell.lblItem.text = subItem.sourceName; tcell.lblItem.textColor = kUITextColor01; if ([subItem.deleteYn boolValue]) { [tcell.lblItem setStrikethrough:tcell.lblItem.text]; } tcell.lblSubItem.text = subItem.sourceSubName; tcell.lblCondition.text = subItem.cmdclsValueMsg; //노드의 액션 값을 세팅함. [tcell.imgvIcon sd_setImageWithURL:[NSURL URLWithString:subItem.imageFileName] placeholderImage:nil options:SDWebImageRefreshCached]; cell = tcell; } else if (section == 3) {//actions - push-message ItemModel *pushItem = [_actions objectKey:@"itemSubTypeCode" eqaulToString:ksItemSubTypeCodeAppPush]; ItemSubModel *subItem = pushItem.subItems[indexPath.row]; RulesDetailPushTableViewCell *tcell = (RulesDetailPushTableViewCell *)[_tableView dequeueReusableCellWithIdentifier:@"PushCellIdentifier"]; tcell.lblMessage.text = subItem.cmdclsValue; cell = tcell; } else if (section == 4) {//conditions RulesDetailConditionTableViewCell *tcell = (RulesDetailConditionTableViewCell *)[_tableView dequeueReusableCellWithIdentifier:@"ConditionCellIdentifier"]; if (!tcell.container.subviews.count) { if ([self isViewLoaded]) { [_rcv beginAppearanceTransition:YES animated:NO]; [tcell.container addSubview:_rcv.view]; [_rcv endAppearanceTransition]; } } tcell.constraintContainerHeight.constant = _rcv.tableHeight; _rcv.isShowingMode = YES; _rcv.conditions = _conditions; cell = tcell; } else if (section == 5) {//execution RulesDetailExecutionTableViewCell *tcell = (RulesDetailExecutionTableViewCell *)[_tableView dequeueReusableCellWithIdentifier:@"ExecutionCellIdentifier"]; tcell.lblExecutionDate.text = !_ruleDetail.latestExecutionDatetime || [_ruleDetail.latestExecutionDatetime isEmptyString] ? @"-" : [CommonUtil localDateFromUTC2:_ruleDetail.latestExecutionDatetime]; tcell.btnUseRule.selected = [_ruleDetail.useYn boolValue]; tcell.statusView.hidden = [JDFacade facade].loginUser.level < 90; //심플 유저일 경우, if (tcell.statusView.hidden) { // tcell.constraintStatusViewBottom.constant = 0; tcell.constraintStatusViewHeight.constant = 0; tcell.statusView.hidden = YES; } else {//마스터일 경우, if (!_btnUseRule) { _btnUseRule = tcell.btnUseRule; } [self changeBtnRunStatus:[_ruleDetail.useYn boolValue]]; if (![tcell.btnUseRule actionsForTarget:self forControlEvent:UIControlEventTouchUpInside]) { [tcell.btnUseRule addTarget:self action:@selector(btnUseRuleTouched:) forControlEvents:UIControlEventTouchUpInside]; } } cell = tcell; } return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [super tableView:tableView didSelectRowAtIndexPath:indexPath]; } #pragma mark - Table Events - (void)btnUseRuleTouched:(id)sender { if ([_ruleDetail.useYn isEqualToString:ksKneetRulesDisable]) { [[JDFacade facade] toast:@"일부 장치 또는 멤버가 삭제되어 비활성 되었습니다.\n편집 후 다시 사용해주세요."]; return; } [self requestChangeRuleStatus]; } - (void)changeBtnRunStatus:(BOOL)isRun { if (isRun) { [_btnUseRule setImage:_btnImageRun forState:UIControlStateNormal]; } else { [_btnUseRule setImage:_btnImageStop forState:UIControlStateNormal]; } } #pragma mark - UI Events - (IBAction)btnOptionTouched:(id)sender { [self toggleOptions:sender]; } - (void)btnCloseTouched:(id)sender { [[JDFacade facade] dismissModalStack:YES completion:nil]; } #pragma mark - MemoryWarning - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end