// // MobileRechargeViewController.swift // GMERemittance // // Created by Sujal on 1/13/18. // Copyright © 2018 Gobal Money Express Co. Ltd. All rights reserved. // import UIKit import ContactsUI class MobileRechargeViewController: UIViewController { @IBOutlet weak var moneyUnitLableOutlet: UILabel! @IBOutlet weak var operatorTypeTextField: UITextField! @IBOutlet weak var segmentedControl: UISegmentedControl! @IBOutlet weak var mobileOperatorsViewOutlet: UIView! @IBOutlet weak var topUpViewOutlet: UIView! @IBOutlet weak var buttonRecharge: UIButton! @IBOutlet weak var viewBinding: UIView! @IBOutlet weak var viewPhoneNumber: UIView! @IBOutlet weak var viewRechargeAmount: UIView! @IBOutlet weak var viewOperator: UIView! @IBOutlet weak var imageViewOperator: UIImageView! @IBOutlet weak var textFieldNumber: UITextField! @IBOutlet weak var textFieldAmount: UITextField! @IBOutlet weak var labelCountryCode: UILabel! @IBOutlet weak var labelTopUp: UILabel! @IBOutlet weak var labelOperator: UILabel! @IBOutlet weak var textFieldCountryName: UITextField! private let contactPicker = CNContactPickerViewController() private var pickerView: UIPickerView = UIPickerView() private var activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView() private var opertorArray = [String]() private var pickerData: [String] = [String]() private var nativeCountry: Bool = true private var operatorSelected: String = "nil" private var amountSelected: String = "nil" private var status:String?? private var amountSelectedFromList: String = "nil" private var amountUnitSelectedFromList: String = "nil" private var mobilerechargeviewmodel = MobileRechargeViewModel() public var amountList = [String]() public var availableAmountBoth: [AvailableAmounts]? public static var mobileRechargeConnectionTimeOutCheck = 0 private var countCheck: Box = Box(nil) override func viewDidLoad() { super.viewDidLoad() textFieldNumber.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged) setUpAnotherLoginListener(genericviewmodel: mobilerechargeviewmodel) setUpNavBar(id: 201, title: "Mobile Recharge") self.viewBinding.clipsToBounds = true self.textFieldNumber.placeholder = "98########" self.mobileOperatorViewListener() self.topUpOperatorViewListener() self.hideKeyboardWhenTappedAround() self.hideMobileDetails() self.requestMobileOperatorApi() mobilerechargeviewmodel.rechargeConnectionTimeOut.value = nil /** connection timeout */ mobilerechargeviewmodel.rechargeConnectionTimeOut.bind { [unowned self] in guard $0 != nil else { return } self.stopLoading() if MobileRechargeViewController.mobileRechargeConnectionTimeOutCheck == 0{ MobileRechargeViewController.mobileRechargeConnectionTimeOutCheck = MobileRechargeViewController.mobileRechargeConnectionTimeOutCheck+1 self.popUpMessage(value: 38) } } /** Check interent connection */ mobilerechargeviewmodel.internetConnection.bind { [unowned self] in guard $0 != nil else { return } self.enableUserInteractions() self.dismissActivityIndicator(activityIndicator: self.activityIndicator) self.popUpMessage(value: 15) } /** Get list of mobile operators like NTC,NCELL and list of amounts as per operator */ mobilerechargeviewmodel.mobileRechargeListBool.bind { [unowned self] in guard $0 != nil else { return } guard $0! else{ self.stopLoading() self.hideMobileDetails() self.textFieldNumber.text = "" self.popUpMessageError(value: 10, message: self.mobilerechargeviewmodel.getInvalideDeviceMessageError()); return } if let object = self.mobilerechargeviewmodel.getRechargeAmounts(){ self.setRechargeAmountsList(availableAmounts : object) } } mobilerechargeviewmodel.isValidNumber.bind{ [unowned self] in guard $0 != nil else { return } guard $0! else { self.hideMobileDetails() return } if Reachability.isConnectedToNetwork() == true{ let position = self.getIndex(operatorName: self.operatorTypeTextField.text!) self.requestApiForListofAmount(telecomId: self.self.mobilerechargeviewmodel.getMobileOperator()[position].telecomId!, mobileNumber: self.textFieldNumber.text!) }else{ self.stopLoading() self.popUpMessage(value: 15) } } mobilerechargeviewmodel.mobileOperatorBool.bind{ [unowned self] in guard $0 != nil else { return } self.textFieldCountryName.text = self.mobilerechargeviewmodel.getMobileOperator().first?.country if self.mobilerechargeviewmodel.getMobileOperator().count>0{ for i in self.mobilerechargeviewmodel.getMobileOperator()[0.. 0{ if let abbreviation = self.mobilerechargeviewmodel.getMobileOperator()[0].abbreviation{ self.operatorTypeTextField.text = abbreviation if self.operatorTypeTextField.text != ""{ self.setInitialValue(operatorType: self.operatorTypeTextField.text!) } } } self.stopLoading() } self.setDelegateAndDataSource() } /** After valid number Api call for amount list */ @objc func textFieldDidChange(){ if textFieldNumber.text?.count == 10{ if Reachability.isConnectedToNetwork(){ self.mobilerechargeviewmodel.updateMobileNumber(enteredNumber: textFieldNumber.text!) if (operatorTypeTextField.text?.count)!>0{ let position = self.getIndex(operatorName: self.operatorTypeTextField.text!) self.requestApiForListofAmount(telecomId: self.mobilerechargeviewmodel.getMobileOperator()[position].telecomId!, mobileNumber: self.textFieldNumber.text!) } else { self.popUpMessageInfo(value: 16, title: "Alert!", message: "Operator is not selected") } } else { stopLoading() self.popUpMessage(value: 15) } }else{ hideMobileDetails() } } /** To call list of amount for topup through phone contact */ func apiCallFromContact(){ if Reachability.isConnectedToNetwork(){ if (operatorTypeTextField.text?.count)!>0{ let position = self.getIndex(operatorName: self.operatorTypeTextField.text!) self.requestApiForListofAmount(telecomId: self.mobilerechargeviewmodel.getMobileOperator()[position].telecomId!, mobileNumber: self.textFieldNumber.text!) } else { self.popUpMessageInfo(value: 16, title: "Alert!", message: "Operator is not selected.") } } else { stopLoading() self.popUpMessage(value: 15) } } /** Set recharge amount list in local object */ func setRechargeAmountsList(availableAmounts: AvailableRechargeAmounts){ self.stopLoading() self.textFieldNumber.resignFirstResponder() self.showMobileDetails() if self.operatorTypeTextField.text != ""{ let index = self.getIndex(operatorName: operatorTypeTextField.text!) if index != 100000{ labelOperator.text = mobilerechargeviewmodel.getMobileOperator()[index].operatorName if let url = mobilerechargeviewmodel.getMobileOperator()[index].iconUrl{ downloadImage(url: Foundation.URL(string: url)!) } } } self.availableAmountBoth?.removeAll() self.amountList.removeAll() self.availableAmountBoth = availableAmounts.availableAmounts if let amountListOfObject = availableAmounts.availableAmounts{ for amount in amountListOfObject{ let value = Float (amount.original) amountList.append((value?.cleanValue)!) } } self.textFieldAmount.text = self.amountList[0] self.moneyUnitLableOutlet.text = "NPR(=\(availableAmountBoth![0].converted) KRW)" } /** Request api for list of amount */ func requestApiForListofAmount(telecomId: String , mobileNumber: String){ self.startLoading() self.mobilerechargeviewmodel.callApiForListofRechargeAmounts(telecomId: telecomId, mobileNumber: mobileNumber) } /** Set delegate and datasource to number of textfield and pickerview */ func setDelegateAndDataSource(){ self.textFieldCountryName.delegate = self self.operatorTypeTextField.delegate = self self.textFieldNumber.delegate = self self.textFieldAmount.delegate = self self.pickerView.dataSource = self self.pickerView.delegate = self self.textFieldAmount.inputView = pickerView } /** Add a view listener for user easilibility */ func topUpOperatorViewListener(){ let tap = UITapGestureRecognizer(target: self, action: #selector(self.topUpOperatorTouchHappen(_:))) topUpViewOutlet.addGestureRecognizer(tap) topUpViewOutlet.isUserInteractionEnabled = true } /** Add a view listener for user easilibility */ func mobileOperatorViewListener(){ let tap = UITapGestureRecognizer(target: self, action: #selector(self.mobileOperatorTouchHappen(_:))) mobileOperatorsViewOutlet.addGestureRecognizer(tap) mobileOperatorsViewOutlet.isUserInteractionEnabled = true } /** Action when user want to fetch number from there contact list */ @IBAction func accessContacts(_ sender: Any) { hideMobileDetails() contactPicker.delegate = self self.present(contactPicker, animated: true, completion: nil) } /** Action when operator value and recharge amount is selected. */ @IBAction func reviewRecharge(_ sender: Any) { guard textFieldAmount.text != "" else { self.popUpMessageError(value: 11, message: "Please select the recharge amount") return } self.performSegue(withIdentifier: "reviewRecharge", sender: nil) } /** Active mobile operator pickerview */ @objc func mobileOperatorTouchHappen(_ sender: UITapGestureRecognizer){ clickLogic(textFieldType: "mobileOperator") } /** Active mobile operator pickerview */ @IBAction func mobileOperatorPickerActionButton(_ sender: Any) { clickLogic(textFieldType: "mobileOperator") } /** Active topUp amount pickerview */ @objc func topUpOperatorTouchHappen(_ sender: UITapGestureRecognizer){ clickLogic(textFieldType: "topUpAmount") } /** Active topUp amount pickerview */ @IBAction func selectTopUpAmount(_ sender: Any) { clickLogic(textFieldType: "topUpAmount") } /** Func to active pickerview as per parameter provided - parameter textFieldType: check which textfield is active */ func clickLogic(textFieldType: String){ switch textFieldType { case "mobileOperator": if let operatorText = operatorTypeTextField.text{ if let index = self.opertorArray.index(of: operatorText){ self.operatorTypeTextField.inputView = self.pickerView self.status = "mobileOperator" operatorTypeTextField.becomeFirstResponder() self.pickerView.selectRow(index, inComponent: 0, animated: true) } } case "topUpAmount": self.textFieldAmount.inputView = self.pickerView self.status = "topUpAmount" textFieldAmount.becomeFirstResponder() if let index = amountList.index(where: { $0 == textFieldAmount.text}) { self.pickerView.selectRow(index, inComponent: 0, animated: true) } default: break } } /** Only support to nepal for now. */ @IBAction func countryDropDownButtonAction(_ sender: Any) { self.popUpMessageInfo(value: 16, title: "Info", message: "Support only to Nepal.") } /** Request api for mobile operator and topup amount */ func requestMobileOperatorApi(){ if mobilerechargeviewmodel.getMobileOperator().count == 0{ mobilerechargeviewmodel.callMobileOperatorApi() self.startLoading() } mobilerechargeviewmodel.setCountryCode(countryCode: labelCountryCode.text!) } /** Request api for mobile operator and topup amount - parameter operatorType: operator selected by user like NTC,NCELL,UTL */ func setInitialValue(operatorType: String){ let position = getIndex(operatorName: operatorType) if self.getTopUpAmount(position: position).count > 0{ textFieldCountryName.text = "Nepal" let floatValue = Float (self.getTopUpAmount(position: position)[0]) textFieldAmount.text = floatValue?.cleanValue moneyUnitLableOutlet.text = "NPR(=\(mobilerechargeviewmodel.getMobileOperator()[position].availableAmounts![0].converted) KRW)" } self.pickerData = self.getTopUpAmount(position: position) } /** Disable user interaction while fetching data from api */ func startLoading(){ self.showProgressHud() // disableUserInteractions() // showActivityIndicator(activityIndicator: activityIndicator) } /** Enable user interaction while fetching data from api */ func stopLoading(){ self.hideProgressHud() } /** Get list of topUp amount as per operator selected - parameter position: operator array index - returns: List of topUp amount */ func getTopUpAmount(position: Int) -> [String]{ var topUpAmount = [String]() if let availableAmount = self.mobilerechargeviewmodel.getMobileOperator()[position].availableAmounts{ print("*******available Amount*******", availableAmount) for i in availableAmount[0..<((availableAmount.count))]{ let value = Float (i.original) topUpAmount.append((value?.cleanValue)!) } } return topUpAmount } /** Picker view done and cancel button */ func pickUp(_ textField : UITextField){ // UIPickerView self.pickerView = UIPickerView(frame:CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 216)) self.pickerView.delegate = self self.pickerView.dataSource = self //self.pickerView.backgroundColor = UIColor.white textField.inputView = self.pickerView // ToolBar let toolBar = UIToolbar() toolBar.barStyle = .default toolBar.isTranslucent = true toolBar.tintColor = UIColor(red: 92/255, green: 216/255, blue: 255/255, alpha: 1) toolBar.sizeToFit() // Adding Button ToolBar let customButton = UIButton() customButton.setTitle("Done", for: .normal) var cancel = UIBarButtonItem() if textField == textFieldAmount { customButton.addTarget(self, action: #selector(MobileRechargeViewController.doneClick), for: .touchUpInside) cancel = UIBarButtonItem(title: "Cancel", style: .done, target: self, action: #selector(self.cancelClick)) cancel.tintColor = UIColor.black }else if textField == operatorTypeTextField{ customButton.addTarget(self, action: #selector(MobileRechargeViewController.doneClickOperator), for: .touchUpInside) cancel = UIBarButtonItem(title: "Cancel", style: .done, target: self, action: #selector(self.cancelClickOperator)) cancel.tintColor = UIColor.black } customButton.setTitleColor(UIColor(hex : 0xED1C24), for: .normal) customButton.frame = CGRect(x: 0, y: 0, width: 60, height: 30) let doneButton = UIBarButtonItem(customView: customButton) let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) toolBar.setItems([cancel,spaceButton, doneButton], animated: false) toolBar.isUserInteractionEnabled = true textField.inputAccessoryView = toolBar } /** Done action in topup pickerview */ @objc func doneClick() { if self.amountSelected != "nil"{ if self.amountSelectedFromList != "nil" && self.amountUnitSelectedFromList != "nil"{ self.textFieldAmount.text = self.amountSelectedFromList self.moneyUnitLableOutlet.text = amountUnitSelectedFromList } }else{ if self.operatorTypeTextField.text != "" { if self.opertorArray.count > 0{ self.textFieldAmount.text = self.amountList[0] } } } self.textFieldAmount.resignFirstResponder() } /** Done action in operator pickerview */ @objc func doneClickOperator(){ if self.operatorSelected != "nil"{ self.operatorTypeTextField.text = self.operatorSelected hideMobileDetails() textFieldNumber.text = "" }else{ if self.mobilerechargeviewmodel.getMobileOperator().count > 0{ self.operatorTypeTextField.text = mobilerechargeviewmodel.getMobileOperator()[0].abbreviation } } self.operatorTypeTextField.resignFirstResponder() } /** Cancel action in topUp pickerview */ @objc func cancelClick(){ self.textFieldAmount.resignFirstResponder() } /** Cancel action in operator pickerview */ @objc func cancelClickOperator(){ self.operatorTypeTextField.resignFirstResponder() } /** Get operator posotion checking operator name - parameter operatorName : operator name like NTC,NCELL,UTL - returns : operator position */ func getIndex(operatorName: String) -> Int{ if let index = opertorArray.index(of: operatorName){ return index } return 100000 } /** Update UI showing list of operators and topUp amount */ func showMobileDetails() { viewRechargeAmount.isHidden = false viewOperator.isHidden = false viewPhoneNumber.layer.cornerRadius = 0 viewBinding.layer.cornerRadius = 10 buttonRecharge.isHidden = false let telecom_index = mobilerechargeviewmodel.getTelecomOperator(isNativeCountry: nativeCountry, mobileNumber: textFieldNumber.text!) textFieldAmount.text = mobilerechargeviewmodel.getTopUpAmount() if nativeCountry { if telecom_index == 1 { labelOperator.text = "NTC" imageViewOperator.image = UIImage(named: "ic_ntc") } else if telecom_index == 2 { labelOperator.text = "NCell" imageViewOperator.image = UIImage(named: "ic_contacts") } else { labelOperator.text = "Operator unknown" imageViewOperator.image = UIImage(named: "ic_contacts") } } else { labelOperator.text = "Korean Telecom" imageViewOperator.image = UIImage(named: "ic_contacts") } textFieldAmount.layer.masksToBounds = true textFieldAmount.layer.borderWidth = 1 textFieldAmount.layer.borderColor = UIColor.white.cgColor if let index = opertorArray.index(of: operatorTypeTextField.text!){ if let availableAmounts = mobilerechargeviewmodel.getMobileOperator()[index].availableAmounts{ if availableAmounts.count > 0{ if let cleanValue = Float (mobilerechargeviewmodel.getMobileOperator()[index].availableAmounts![0].original)?.cleanValue{ textFieldAmount.text = cleanValue } if let abbreviationValue = mobilerechargeviewmodel.getMobileOperator()[index].abbreviation{ labelOperator.text = abbreviationValue } if let url = mobilerechargeviewmodel.getMobileOperator()[index].iconUrl{ downloadImage(url: Foundation.URL(string: url)!) } } }else{ textFieldAmount.text = "" moneyUnitLableOutlet.text = "" } } } /** Hide view if no data is available */ func hideMobileDetails() { viewBinding.layer.cornerRadius = 0.0 viewPhoneNumber.layer.cornerRadius = 10 viewRechargeAmount.isHidden = true viewOperator.isHidden = true buttonRecharge.isHidden = true } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "reviewRecharge" { if operatorTypeTextField.text != ""{ let position = getIndex(operatorName: operatorTypeTextField.text!) if position != 100000{ if let telecomId = mobilerechargeviewmodel.getMobileOperator()[position].telecomId{ mobilerechargeviewmodel.setTelecomId(telecomId: telecomId) } } } let reviewRechargeViewController = segue.destination as! MobileRechargeReviewViewController reviewRechargeViewController.convertedData = "\(self.moneyUnitLableOutlet.text!)" reviewRechargeViewController.transferAmount = self.textFieldAmount.text if let operatorType = operatorTypeTextField.text { if operatorTypeTextField.text != ""{ if let index = self.opertorArray.index(of: operatorType){ reviewRechargeViewController.operatorUrl = self.mobilerechargeviewmodel.getMobileOperator()[index].iconUrl } } } reviewRechargeViewController.mobilerechargeviewmodel = self.mobilerechargeviewmodel } } func getDataFromUrl(url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> ()) { URLSession.shared.dataTask(with: url) { data, response, error in completion(data, response, error) }.resume() } /** Set image in imageview - parameter url: image url provided by API */ func downloadImage(url: URL) { getDataFromUrl(url: url) { data, response, error in guard let data = data, error == nil else { return } DispatchQueue.main.async() { if let data = UIImage(data: data){ self.imageViewOperator.image = data } } } } } extension MobileRechargeViewController: UITextFieldDelegate { func textFieldDidBeginEditing(_ textField: UITextField) { if textField == textFieldAmount { self.status = "topUpAmount" self.pickUp(textField) if let index = pickerData.index(where: { $0 == textFieldAmount.text}) { self.pickerView.selectRow(index, inComponent: 0, animated: true) } } else if textField == operatorTypeTextField{ self.status = "mobileOperator" self.pickUp(textField) if self.operatorTypeTextField.text != ""{ let position = getIndex(operatorName: self.operatorTypeTextField.text!) if self.getTopUpAmount(position: position).count > 0{ let floatValue = Float (self.getTopUpAmount(position: position)[0]) textFieldAmount.text = floatValue?.cleanValue if mobilerechargeviewmodel.getMobileOperator().count > 0{ //moneyUnitLableOutlet.text = "NPR(=\(mobilerechargeviewmodel.getMobileOperator()[position].availableAmounts![0].converted) KRW)" } } self.pickerData = self.getTopUpAmount(position: position) } } } func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { if textField == textFieldNumber{ let newString = (textField.text! as NSString).replacingCharacters(in: range, with: string) if newString.count > 10{ return false } else { return true } } else if textField == textFieldCountryName { textField.resignFirstResponder() } return false } func textFieldDidEndEditing(_ textField: UITextField) { if textField == textFieldAmount{ self.textFieldAmount.resignFirstResponder() } } } extension MobileRechargeViewController: UIPickerViewDataSource, UIPickerViewDelegate { func numberOfComponents(in pickerView: UIPickerView) -> Int { return 1 } func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { if self.status == "topUpAmount"{ return amountList.count } else if self.status == "mobileOperator"{ return opertorArray.count } return 0 } func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { if self.status == "topUpAmount"{ return amountList[row] } else if self.status == "mobileOperator"{ return opertorArray[row] } return "" } func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { if self.status == "topUpAmount"{ self.amountSelected = amountList[row] if self.amountSelected != "nil"{ if self.operatorTypeTextField.text != ""{ if mobilerechargeviewmodel.getMobileOperator().count > 0{ amountSelectedFromList = self.amountSelected amountUnitSelectedFromList = "NPR(=\(availableAmountBoth![row].converted) KRW)" } } } } else if self.status == "mobileOperator"{ self.operatorSelected = opertorArray[row] } } } extension MobileRechargeViewController: CNContactPickerDelegate { func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) { let phoneNumberCount = contact.phoneNumbers.count guard phoneNumberCount > 0 else { dismiss(animated: true) { self.popUpMessageError(value: 10, message: "Selected contact does not have a number") } return } if phoneNumberCount == 1 { setNumberFromContact(contactNumber: contact.phoneNumbers[0].value.stringValue) self.apiCallFromContact() } else { let alertController = UIAlertController(title: "Select one of the numbers", message: nil, preferredStyle: .alert) for i in 0...phoneNumberCount-1 { let phoneAction = UIAlertAction(title: contact.phoneNumbers[i].value.stringValue, style: .default, handler: { alert -> Void in self.setNumberFromContact(contactNumber: contact.phoneNumbers[i].value.stringValue) self.apiCallFromContact() }) alertController.addAction(phoneAction) } let cancelAction = UIAlertAction(title: "Cancel", style: .destructive, handler: { alert -> Void in }) alertController.addAction(cancelAction) dismiss(animated: true) { self.present(alertController, animated: true, completion: nil) } } } func setNumberFromContact(contactNumber: String) { var contactNumber = contactNumber.replacingOccurrences(of: "-", with: "") contactNumber = contactNumber.replacingOccurrences(of: "(", with: "") contactNumber = contactNumber.replacingOccurrences(of: ")", with: "") contactNumber = contactNumber.removeWhitespacesInBetween() guard contactNumber.count >= 10 else { dismiss(animated: true) { self.popUpMessageError(value: 10, message: "Selected contact does not have a valid number") } return } textFieldNumber.text = String(contactNumber.suffix(10)) mobilerechargeviewmodel.updateMobileNumber(enteredNumber: textFieldNumber.text!) } func contactPickerDidCancel(_ picker: CNContactPickerViewController) { } } extension Float { var cleanValue: String { return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(self) } }