// // ThingsDetailViewController.m // kneet // // Created by Jason Lee on 3/16/15. // Copyright (c) 2015 ntels. All rights reserved. // #import "RequestHandler.h" #import "DeviceModel.h" #import "CustomImageView.h" #import "CustomLabel.h" #import "CustomTextField.h" #import "CustomButton.h" #import "UIImageView+WebCache.h" #import "CommandClassControlDetailView.h" #import "ThingsModifyViewController.h" #import "ThingsInfoViewController.h" #import "ThingsDetailViewController.h" #import "ValidateUtil.h" #import "ThingsViewController.h" #import "CustomAlertView.h" #import "ModifySecureKeyPopupView.h" @implementation ThingsDetailImageViewCell - (void)awakeFromNib { self.backgroundColor = [UIColor clearColor]; self.selectionStyle = UITableViewCellSelectionStyleNone; } @end @implementation ThingsDetailControlViewCell - (void)awakeFromNib { self.backgroundColor = [UIColor clearColor]; self.selectionStyle = UITableViewCellSelectionStyleNone; } @end @interface ThingsDetailViewController () { DeviceDetailModel *_deviceDetail; ThingsModifyViewController *_mvc; ThingsInfoViewController *_ivc; CGFloat _containerBottom; BOOL _isNotFirstLoading; CustomTextField2 *_txtDeviceName; CustomImageView *_imgvDevice; ModifySecureKeyPopupView *_kpopup; } @end #pragma mark - Class Definition @implementation ThingsDetailViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. [self initUI]; [self prepareViewDidLoad]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; self.title = NSLocalizedString(@"내 장치 상세",nil); } - (void)initUI { [self generateOptionButton]; //initialize tableView _tableView.dataSource = self; _tableView.delegate = self; _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; _tableView.backgroundColor = [UIColor clearColor]; _tableView.tableFooterView = [[UIView alloc] init]; //this call table events; _txtDeviceName.keyboardType = UIKeyboardTypeDefault; _txtDeviceName.returnKeyType = UIReturnKeyDone; } - (void)setThingsDetailPopoverOptions { //set Popover Contents __weak typeof(self) weakSelf = self; _popooverOptionArray = [[NSMutableArray alloc] init]; [_popooverOptionArray addObject:@{@"menuName" : NSLocalizedString(@"새로 고침",nil), @"iconName": @"tp_01_img_bg_morepopup_icon_refresh", @"target": weakSelf, @"selector": [NSValue valueWithPointer:@selector(requestDeviceDetails)]}]; [_popooverOptionArray addObject:@{@"menuName" : NSLocalizedString(@"장치 정보 보기",nil), @"iconName": @"tp_01_img_bg_morepopup_icon_detail", @"target": weakSelf, @"selector": [NSValue valueWithPointer:@selector(showThingsDetailInfo)]}]; if ([JDFacade facade].loginUser.level > 10) { [_popooverOptionArray addObject:@{@"menuName" : NSLocalizedString(@"이름/아이콘 변경",nil), @"iconName": @"tp_01_img_bg_morepopup_icon_edit", @"target": weakSelf, @"selector": [NSValue valueWithPointer:@selector(modifyThingsName)]}]; if (_deviceDetail.activationCode && ![_deviceDetail.activationCode isEmptyString]){//device_type = controller_primary [_popooverOptionArray addObject:@{@"menuName" : NSLocalizedString(@"장치등록 보안키 변경", @"장치등록 보안키 변경"), @"iconName": @"tp_01_img_bg_morepopup_icon_edit", @"target": weakSelf, @"selector": [NSValue valueWithPointer:@selector(modifySecureKey)]}]; } if ([_deviceDetail.deviceProfileId isEqualToString:ksDeviceProfileIdUnknown]) {//장치가 언노운일 경우, [_popooverOptionArray addObject:@{@"menuName" : NSLocalizedString(@"장치유형 선택", @"장치유형 선택"), @"iconName": @"tp_01_img_bg_morepopup_icon_dtype", @"target": weakSelf, @"selector": [NSValue valueWithPointer:@selector(modifyDeviceType)]}]; } //FIXME : for demo // if ([_deviceDetail.removableYn boolValue]) {//삭제 가능일 경우, if ([_deviceDetail.deviceProfileId isEqualToString:@"20028"] || [_deviceDetail.deviceProfileId isEqualToString:@"20029"]) { [_popooverOptionArray addObject:@{@"menuName" : NSLocalizedString(@"장치 삭제",nil), @"iconName": @"tp_01_img_bg_morepopup_icon_del", @"target": weakSelf, @"selector": [NSValue valueWithPointer:@selector(removeThings)]}]; } } } - (void)prepareViewDidLoad { [self performSelector:@selector(requestDeviceDetails) withObject:nil afterDelay:0.0f]; } #pragma mark - Main Logic - (void)requestDeviceDetails { NSString *path = [NSString stringWithFormat:API_GET_DEVICE_DETAIL, _device.deviceId]; [[RequestHandler handler] sendAsyncGetRequestAPIPath:path parameters:nil modelClass:[DeviceDetailModel class] completion:^(id responseObject) { if (!responseObject) {//응답결과가 잘못되었거나 없을 경우, return; } _deviceDetail = (DeviceDetailModel *)responseObject; if (_deviceDetail) {//API 성공 , [self resetOptions]; //옵션 메뉴 초기화 [self setThingsDetailPopoverOptions]; [self setDeviceContents]; } } failure:^(id errorObject) { JDErrorModel *error = (JDErrorModel *)errorObject; [[JDFacade facade] alert:error.errorMessage]; }]; } - (void)setDeviceContents { [_tableView reloadData]; } - (void)requestDeviceUpdate { //parameters NSDictionary *parameter = @{@"image_sequence": _mvc && _mvc.selectedIcon ? _mvc.selectedIcon.imageSequence : ksEmptyString, @"device_name": _txtDeviceName.text}; NSString *path = [NSString stringWithFormat:API_GET_DEVICE_UPDATE, _deviceDetail.deviceId]; [[RequestHandler handler] sendAsyncPostRequestAPIPath:path parameters:parameter modelClass:[JDJSONModel class] completion:^(id responseObject) { _device.deviceName = _deviceDetail.deviceName = _txtDeviceName.text; _device.imageFileName = _deviceDetail.imageFileName = _mvc && _mvc.selectedIcon ? _mvc.selectedIcon.imageFileName : _device.imageFileName; [self closeChildViewController:_mvc completionHandler:nil]; [_tableView reloadData]; //리스트를 다시 로드함. // ThingsViewController *vc = [[JDFacade facade] viewControllerOnNaviationController:[ThingsViewController class]]; // [vc.tableView reloadData]; } failure:^(id errorObject) { JDErrorModel *error = (JDErrorModel *)errorObject; [[JDFacade facade] alert:error.errorMessage]; }]; } - (void)requestDeleteDevice { //parameters NSString *path = [NSString stringWithFormat:API_DELETE_DEVICE, _deviceDetail.deviceId]; [[RequestHandler handler] sendAsyncRequestAPIPath:path method:ksHTTPRequestDELETE parameters:nil modelClass:[JDJSONModel class] showLoadingView:YES completion:^(id responseObject) { [[JDFacade facade] toast:NSLocalizedString(@"장치가 삭제되었습니다", @"장치가 삭제되었습니다")]; // if ([JDFacade facade].loginHomeGroup.deviceId && ![[JDFacade facade].loginHomeGroup.deviceId isEmptyString]) { // if ([[JDFacade facade].loginHomeGroup.deviceId isEqualToString:_deviceDetail.deviceId]) {//현재 홈의 스마튼폰일 경우, // [JDFacade facade].loginHomeGroup.deviceId = nil; // [JDFacade facade].loginHomeGroup.deviceAuthorization = nil; // [JDFacade facade].loginHomeGroup.deviceKey = nil; // } // } //리스트를 다시 로드함. ThingsViewController *vc = [[JDFacade facade] viewControllerOnNaviationController:[ThingsViewController class]]; [vc prepareViewDidLoad]; [self.navigationController popToRootViewControllerAnimated:YES]; } failure:^(id errorObject) { JDErrorModel *error = (JDErrorModel *)errorObject; [[JDFacade facade] alert:error.errorMessage]; }]; } //장치등록 보안키 변경 - (void)requestModifySecureKey { //parameters NSDictionary *parameter = @{@"device_id": _deviceDetail.deviceId, @"change_device_password": _kpopup.txtSecureCode.text}; NSString *path = [NSString stringWithFormat:ksEmptyString];//API_POST_PARTNER_PASSWD]; [[RequestHandler handler] sendAsyncPostRequestAPIPath:path parameters:parameter modelClass:[JDJSONModel class] completion:^(id responseObject) { [[JDFacade facade] toast:NSLocalizedString(@"변경되었습니다", @"변경되었습니다")]; } failure:^(id errorObject) { JDErrorModel *error = (JDErrorModel *)errorObject; [[JDFacade facade] alert:error.errorMessage]; }]; } #pragma mark - UITableView DataSource & Delegate - (ThingsDetailImageViewCell *)imageCell { return (ThingsDetailImageViewCell *)[_tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return _deviceDetail.nodes ? _deviceDetail.nodes.count + 1 : 0; //append for ImageCell } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { CGFloat height = 0.0f, titlePadding = 0.0f; if (indexPath.row == 0) { height = 152.0f; } else { NodeModel *node = _deviceDetail.nodes[indexPath.row-1]; //다원플러그일 경우, BOOL isControlDAWONPlug = [_deviceDetail.deviceMfId isEqualToString:@"DAWON"] && [_deviceDetail.deviceProfileId isEqualToString:@"20004"]; CommandClassControlView *controlView = nil; if (node.cmdclsType == CmdClsTypeMeterCurrent && isControlDAWONPlug) { controlView = [CommandClassControlDetailView viewForCommandClass:CmdClsTypeMeterCurrentForDAWON]; } else if (node.cmdclsType == CmdClsTypeMeterTotal && isControlDAWONPlug) { controlView = [CommandClassControlDetailView viewForCommandClass:CmdClsTypeMeterTotalForDAWON]; titlePadding = indexPath.row < _deviceDetail.nodes.count ? 25 : 50; } else { controlView = [CommandClassControlDetailView viewForCommandClass:node.cmdclsType]; titlePadding = 50.0f; } controlView.node = node; height = titlePadding + [controlView sizeForIntrinsic].height; //title label + margin } return height; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *cellIdentifier = indexPath.row == 0 ? @"ImageCellIdentifier" : @"CellIdentifier"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; if (cell == nil) { if (indexPath.row == 0) { ThingsDetailImageViewCell *icell = [[ThingsDetailImageViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; cell = icell; } else { ThingsDetailControlViewCell *cCell = [[ThingsDetailControlViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; cell = cCell; } } if (indexPath.row == 0) {//디바이스 이미지 및 네임. ThingsDetailImageViewCell *icell = (ThingsDetailImageViewCell *)cell; icell.lblDeviceName.text = _deviceDetail.deviceName; icell.txtDeviceName.text = _deviceDetail.deviceName; [icell.imgvDevice sd_setImageWithURL:[NSURL URLWithString:_deviceDetail.imageFileName] placeholderImage:nil]; if (_deviceDetail.networkYn && ![_deviceDetail.networkYn isEqualToString:@"none"] && ![_deviceDetail.networkYn boolValue]) { if (!icell.imgvDevice.subviews.count) { UIImageView *imgvOffline = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"tp_01_img_things_offline_cover"]]; CGRect ir = icell.imgvDevice.frame; ir.origin = (CGPoint){.x=0, .y=0}; imgvOffline.frame = ir; [icell.imgvDevice addSubview:imgvOffline]; } else { [icell.imgvDevice bringSubviewToFront:icell.imgvDevice.subviews.firstObject]; } } else { if (icell.imgvDevice.subviews.count) { [icell.imgvDevice.subviews.firstObject removeFromSuperview]; } } if (!_txtDeviceName) { _txtDeviceName = icell.txtDeviceName; } if (!_imgvDevice) { _imgvDevice = icell.imgvDevice; } icell.txtDeviceName.alpha = 0.0f; } else { NodeModel *node = _deviceDetail.nodes[indexPath.row-1]; ThingsDetailControlViewCell *cCell = (ThingsDetailControlViewCell *)cell; //뷰를 초기화함. [[cCell.controlContainerView subviews] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { UIView *subview = (UIView *)obj; [subview removeFromSuperview]; }]; cCell.lblNodeTitle.text = node.nodeName; //다원플러그일 경우, BOOL isControlDAWONPlug = [_deviceDetail.deviceMfId isEqualToString:@"DAWON"] && [_deviceDetail.deviceProfileId isEqualToString:@"20004"]; CommandClassControlView *controlView = nil; if (node.cmdclsType == CmdClsTypeSensorBinary) {//미터 커렌트 - 그래프 controlView = [CommandClassControlDetailView viewForCommandClass:CmdClsTypeMeterCurrentForDAWON]; cCell.constraintContainerTop.constant = 0; cCell.constraintNodeTitleLeft.constant = 0; cCell.constraintNodeTitleTop.constant = ([controlView sizeForIntrinsic].height / 2) - (25/2) - 15; cCell.lblNodeTitle.textAlignment = NSTextAlignmentCenter; } else if (node.cmdclsType == CmdClsTypeMeterTotal && isControlDAWONPlug) {//미터 토탈 - 아이콘 controlView = [CommandClassControlDetailView viewForCommandClass:CmdClsTypeMeterTotalForDAWON]; cCell.constraintContainerTop.constant = 25; cCell.constraintNodeTitleLeft.constant = 120; cCell.constraintNodeTitleTop.constant = 28; cCell.lblNodeTitle.textAlignment = NSTextAlignmentLeft; } else { controlView = [CommandClassControlDetailView viewForCommandClass:node.cmdclsType]; cCell.constraintContainerTop.constant = 25; cCell.constraintNodeTitleLeft.constant = 0; cCell.constraintNodeTitleTop.constant = 0; cCell.lblNodeTitle.textAlignment = NSTextAlignmentCenter; } node.deviceId = _deviceDetail.deviceId; controlView.node = node; cCell.controlContainerView.hidden = !controlView; if (!cCell.controlContainerView.hidden) { UIView *superview = cCell.controlContainerView; cCell.constraintContainerHeight.constant = [controlView sizeForIntrinsic].height; [superview addSubview:controlView]; [controlView mas_makeConstraints:^(MASConstraintMaker *make) { make.size.mas_equalTo(controlView.frame.size); make.center.equalTo(superview); }]; // NSLog(@"%s\n %@", __PRETTY_FUNCTION__, cCell.controlContainerView); } } return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; } - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { // Remove seperator inset if ([cell respondsToSelector:@selector(setSeparatorInset:)]) { [cell setSeparatorInset:UIEdgeInsetsZero]; } // Prevent the cell from inheriting the Table View's margin settings if ([cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)]) { [cell setPreservesSuperviewLayoutMargins:NO]; } // Explictly set your cell's layout margins if ([cell respondsToSelector:@selector(setLayoutMargins:)]) { [cell setLayoutMargins:UIEdgeInsetsZero]; } } #pragma mark - UI Events //상세 보기 - (void)showThingsDetailInfo { if ([_mvc.view superview]) { [self closeChildViewController:_mvc completionHandler:^{ [self showThingsDetailInfo]; }]; return; } _tableView.scrollEnabled = NO; if (!_ivc) { _ivc = (ThingsInfoViewController *)[CommonUtil instantiateViewControllerWithIdentifier:@"ThingsInfoViewController" storyboardName:@"Things"]; _ivc.deviceDetail = _deviceDetail; [self addChildViewController:_ivc]; [_ivc didMoveToParentViewController:self]; } [_containerView addSubview:_ivc.view]; if (![_ivc.btnClose actionsForTarget:self forControlEvent:UIControlEventTouchUpInside]) { __weak typeof(self) weakSelf = self; [_ivc.btnClose addTarget:weakSelf action:@selector(btnCloseTouched:) forControlEvents:UIControlEventTouchUpInside]; } _containerBottom = _constraintContainerBottom.constant; _constraintContainerBottom.constant = 0.0f; [UIView animateWithDuration:kfAnimationDur animations:^{ [_containerView layoutIfNeeded]; }]; } //장치명 변경 - (void)modifyThingsName { if ([_ivc.view superview]) { [self closeChildViewController:_ivc completionHandler:^{ [self modifyThingsName]; }]; return; } _tableView.scrollEnabled = NO; if (!_mvc) { _mvc = (ThingsModifyViewController *)[CommonUtil instantiateViewControllerWithIdentifier:@"ThingsModifyViewController" storyboardName:@"Things"]; _mvc.device = _deviceDetail; [self addChildViewController:_mvc]; [_mvc didMoveToParentViewController:self]; } [_containerView addSubview:_mvc.view]; if (![_mvc.btnSave actionsForTarget:self forControlEvent:UIControlEventTouchUpInside]) { __weak typeof(self) weakSelf = self; [_mvc.btnSave addTarget:weakSelf action:@selector(btnSaveTouched:) forControlEvents:UIControlEventTouchUpInside]; [_mvc.btnCancel addTarget:weakSelf action:@selector(btnCancelTouched:) forControlEvents:UIControlEventTouchUpInside]; } _containerBottom = _constraintContainerBottom.constant; _constraintContainerBottom.constant = 0.0f; [UIView animateWithDuration:kfAnimationDur animations:^{ [self imageCell].txtDeviceName.alpha = 1.0f; [self imageCell].lblDeviceName.alpha = 0.0f; [_containerView layoutIfNeeded]; }]; } //장치등록 보안키 변경 - (void)modifySecureKey { if (!_kpopup) { _kpopup = [[ModifySecureKeyPopupView alloc] initFromNib]; } [_kpopup showWithCompletion:^(CustomAlertView *alertView, NSInteger buttonIndex) { if (buttonIndex == 0) {//OK [self requestModifySecureKey]; } }]; } //장치 유형 변경 - (void)modifyDeviceType { //goto choose device type } //디바이스 삭제 - (void)removeThings { CustomAlertView *alert = [[CustomAlertView alloc] initWithTitle:NSLocalizedString(@"알림", @"알림") message:NSLocalizedString(@"장치를 삭제하시겠습니까?\n이 장치에 속한 하위 장치가 있을 경우 함께 삭제됩니다\n\n이 장치를 사용중인 홈 규칙과\n멀티 제어가 비활성 상태로 변경됩니다\n\n신중하게 결정하세요", @"장치를 삭제하시겠습니까?\n이 장치에 속한 하위 장치가 있을 경우 함께 삭제됩니다\n\n이 장치를 사용중인 홈 규칙과\n멀티 제어가 비활성 상태로 변경됩니다\n\n신중하게 결정하세요") delegate:nil OKButtonTitle:NSLocalizedString(@"삭제", @"삭제") cancelButtonTitle:NSLocalizedString(@"취소", @"취소")]; [alert showWithCompletion:^(CustomAlertView *alertView, NSInteger buttonIndex) { if (buttonIndex == 0) {//OK //삭제 후 장치목록으로 이동요 [self requestDeleteDevice]; } }]; } - (void)btnSaveTouched:(id)sender { //validate if (!_txtDeviceName || ![ValidateUtil validateTextfiled:_txtDeviceName type:ValidateTypeNull title:NSLocalizedString(@"장치명", @"장치명")]) { return; } //TOOD : request [self requestDeviceUpdate]; } - (void)btnCancelTouched:(id)sender { [self closeChildViewController:_mvc completionHandler:nil]; } - (void)closeChildViewController:(UIViewController *)vc completionHandler:(JDFacadeCompletionCallBackHandler)completionHander { _constraintContainerBottom.constant = _containerBottom; [UIView animateWithDuration:kfAnimationDur animations:^{ [self imageCell].txtDeviceName.alpha = 0.0f; [self imageCell].lblDeviceName.alpha = 1.0f; [self.view layoutIfNeeded]; } completion:^(BOOL finished) { _tableView.scrollEnabled = YES; [vc.view removeFromSuperview]; if (completionHander) { completionHander(); } }]; } - (void)btnCloseTouched:(id)sender { [self closeChildViewController:_ivc completionHandler:nil]; } #pragma mark - MemoryWarning - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end