<commit_before>//
//  IncFormPickerSelectionCell.swift
//  GigSalad
//
//  Created by <NAME> on 4/26/17.
//  Copyright © 2017 Incipia. All rights reserved.
//

import UIKit

class IncFormPickerSelectionCell: IncFormBindableElementCell {
   // MARK: - Label Outlets
   @IBOutlet fileprivate var _nameLabel: UILabel!
   @IBOutlet fileprivate var _detailLabel: UILabel!
   @IBOutlet fileprivate var _buttonLabel: UILabel!
   
   // MARK: - View Outlets
   @IBOutlet fileprivate var _buttonBackgroundView: UIView!
   @IBOutlet fileprivate var _leftAccessoryImageView: UIImageView!
   @IBOutlet fileprivate var _rightAccessoryImageView: UIImageView!
   @IBOutlet fileprivate var _pickerView: UIPickerView!
   @IBOutlet fileprivate var _pickerBackgroundView: UIView!
   
   // MARK: - Constraint Outlets
   @IBOutlet fileprivate var _leftAccessoryImageViewWidthConstraint: NSLayoutConstraint!
   @IBOutlet fileprivate var _rightAccessoryImageViewWidthConstraint: NSLayoutConstraint!
   @IBOutlet fileprivate var _leftImageViewHorizontalSpaceConstraint: NSLayoutConstraint!
   @IBOutlet fileprivate var _rightImageViewHorizontalSpaceConstraint: NSLayoutConstraint!
   @IBOutlet fileprivate var _nameVerticalSpaceConstraint: NSLayoutConstraint!
   @IBOutlet fileprivate var _detailVerticalSpaceConstraint: NSLayoutConstraint!
   @IBOutlet fileprivate var _buttonHeightConstraint: NSLayoutConstraint!
   
   // MARK: - Private Properties
   fileprivate var _options: [(option: IncFormPickerSelection.Option, dataValue: Data)] = []
   fileprivate var _optionStyle: IncFormTextStyle = IncFormTextStyle()
   fileprivate var _selectedOption: IncFormPickerSelection.Option? {
      let selectedOptions = _options.filter { $0.option.isSelected }
      guard selectedOptions.count <= 1 else { fatalError() }
      return selectedOptions.first?.option
   }
   fileprivate var _selectedValue: Any? {
      get { return _selectedOption?.value }
      set {
         guard !_options.isEmpty else { return }
         guard let element = element as? IncFormPickerSelection else { fatalError() }
         var selectIndex: Int? = nil
         if let someValue = newValue {
            let dataValue = IncFormElementCell.dataValue(someValue)
            for (index, option) in _options.enumerated() {
               if option.dataValue == dataValue {
                  _options[index].option.isSelected = true
                  selectIndex = index
               } else {
                  _options[index].option.isSelected = false
               }
            }
         } else {
            for (index, _) in _options.enumerated() {
               _options[index].option.isSelected = false
            }
         }
         _updateButton(with: element)
         _updateOptionStyle(with: element.configuration.optionStyle)
         if _pickerView.selectedRow(inComponent: 0) != selectIndex {
            _pickerView.selectRow(selectIndex ?? 0, inComponent: 0, animated: true)
         }
         trySetBoundValue(newValue, for: .anyValue)
      }
   }
   
   // MARK: - Overridden
   override func awakeFromNib() {
      super.awakeFromNib()
      
      let button = UIButton()
      button.translatesAutoresizingMaskIntoConstraints = false
      _buttonBackgroundView.addSubview(button)
      button.topAnchor.constraint(equalTo: _buttonBackgroundView.topAnchor).isActive = true
      button.bottomAnchor.constraint(equalTo: _buttonBackgroundView.bottomAnchor).isActive = true
      button.leftAnchor.constraint(equalTo: _buttonBackgroundView.leftAnchor).isActive = true
      button.rightAnchor.constraint(equalTo: _buttonBackgroundView.rightAnchor).isActive = true
      
      let fadeSelector = #selector(IncFormPickerSelectionCell._fadePickerButton)
      button.addTarget(self, action: fadeSelector, for: .touchDown)
      button.addTarget(self, action: fadeSelector, for: .touchDragEnter)
      let unfadeSelector = #selector(IncFormPickerSelectionCell._unfadePickerButton)
      button.addTarget(self, action: unfadeSelector, for: .touchDragExit)
      button.addTarget(self, action: unfadeSelector, for: .touchCancel)
      let touchUpSelector = #selector(IncFormPickerSelectionCell._pickerButtonTouchUpInside)
      button.addTarget(self, action: touchUpSelector, for: .touchUpInside)
      
      _pickerBackgroundView.layer.cornerRadius = 6.0
   }
   
   override func configure(with component: IncFormElemental) {
      guard let element = component as? IncFormPickerSelection else { fatalError() }
      super.configure(with: component)
      let content = element.content
      let config = element.configuration
      if let layoutDelegate = config.layoutDelegate {
         self.layoutDelegate = layoutDelegate
      }
      
      _nameLabel.text = content.name
      _detailLabel.text = content.detail
      _nameLabel.font = config.nameStyle.font
      _buttonBackgroundView.backgroundColor = config.buttonBackgroundColor
      _detailLabel.font = config.detailStyle?.font
      _nameLabel.textColor = config.nameStyle.color
      _detailLabel.textColor = config.detailStyle?.color
      _nameVerticalSpaceConstraint.constant = content.name != nil ? 10 : 0
      _detailVerticalSpaceConstraint.constant = content.detail != nil ? 10 : 0
      _buttonHeightConstraint.constant = config.buttonHeight
      
      _options = element.content.options.map { return (option: $0, dataValue: IncFormElementCell.dataValue($0.value)) }
      guard Set(_options.map { return $0.dataValue }).count == _options.count else { fatalError() }

      _pickerBackgroundView.backgroundColor = config.buttonBackgroundColor
      _pickerView.reloadAllComponents()

      _selectedValue = _selectedOption?.value
      
      _updateIndicatorColor()
      _updateAccessoryImages(with: element)
   }
   
   override class func contentSize(for element: IncFormElemental, constrainedWidth width: CGFloat) -> CGSize {
      guard let element = element as? IncFormPickerSelection else { fatalError() }
      let content = element.content
      let config = element.configuration
      let finalWidth = config.width ?? width
      
      guard config.height == nil else {
         return CGSize(width: finalWidth, height: config.height!)
      }
      
      let nameHeight = content.name?.heightWithConstrainedWidth(width: width, font: config.nameStyle.font) ?? 0
      let namePadding: CGFloat = content.name != nil ? 10 : 0
      let pickerHeight: CGFloat = element.inputState == .focused ? 216 : 0<commit_msg>Fixed a bug that sometimes caused picker elements' right accessory view to appear upside down before the picker was focused.<commit_after>//
//  IncFormPickerSelectionCell.swift
//  GigSalad
//
//  Created by <NAME> on 4/26/17.
//  Copyright © 2017 Incipia. All rights reserved.
//

import UIKit

class IncFormPickerSelectionCell: IncFormBindableElementCell {
   // MARK: - Label Outlets
   @IBOutlet fileprivate var _nameLabel: UILabel!
   @IBOutlet fileprivate var _detailLabel: UILabel!
   @IBOutlet fileprivate var _buttonLabel: UILabel!
   
   // MARK: - View Outlets
   @IBOutlet fileprivate var _buttonBackgroundView: UIView!
   @IBOutlet fileprivate var _leftAccessoryImageView: UIImageView!
   @IBOutlet fileprivate var _rightAccessoryImageView: UIImageView!
   @IBOutlet fileprivate var _pickerView: UIPickerView!
   @IBOutlet fileprivate var _pickerBackgroundView: UIView!
   
   // MARK: - Constraint Outlets
   @IBOutlet fileprivate var _leftAccessoryImageViewWidthConstraint: NSLayoutConstraint!
   @IBOutlet fileprivate var _rightAccessoryImageViewWidthConstraint: NSLayoutConstraint!
   @IBOutlet fileprivate var _leftImageViewHorizontalSpaceConstraint: NSLayoutConstraint!
   @IBOutlet fileprivate var _rightImageViewHorizontalSpaceConstraint: NSLayoutConstraint!
   @IBOutlet fileprivate var _nameVerticalSpaceConstraint: NSLayoutConstraint!
   @IBOutlet fileprivate var _detailVerticalSpaceConstraint: NSLayoutConstraint!
   @IBOutlet fileprivate var _buttonHeightConstraint: NSLayoutConstraint!
   
   // MARK: - Private Properties
   fileprivate var _options: [(option: IncFormPickerSelection.Option, dataValue: Data)] = []
   fileprivate var _optionStyle: IncFormTextStyle = IncFormTextStyle()
   fileprivate var _selectedOption: IncFormPickerSelection.Option? {
      let selectedOptions = _options.filter { $0.option.isSelected }
      guard selectedOptions.count <= 1 else { fatalError() }
      return selectedOptions.first?.option
   }
   fileprivate var _selectedValue: Any? {
      get { return _selectedOption?.value }
      set {
         guard !_options.isEmpty else { return }
         guard let element = element as? IncFormPickerSelection else { fatalError() }
         var selectIndex: Int? = nil
         if let someValue = newValue {
            let dataValue = IncFormElementCell.dataValue(someValue)
            for (index, option) in _options.enumerated() {
               if option.dataValue == dataValue {
                  _options[index].option.isSelected = true
                  selectIndex = index
               } else {
                  _options[index].option.isSelected = false
               }
            }
         } else {
            for (index, _) in _options.enumerated() {
               _options[index].option.isSelected = false
            }
         }
         _updateButton(with: element)
         _updateOptionStyle(with: element.configuration.optionStyle)
         if _pickerView.selectedRow(inComponent: 0) != selectIndex {
            _pickerView.selectRow(selectIndex ?? 0, inComponent: 0, animated: true)
         }
         trySetBoundValue(newValue, for: .anyValue)
      }
   }
   
   // MARK: - Overridden
   override func awakeFromNib() {
      super.awakeFromNib()
      
      let button = UIButton()
      button.translatesAutoresizingMaskIntoConstraints = false
      _buttonBackgroundView.addSubview(button)
      button.topAnchor.constraint(equalTo: _buttonBackgroundView.topAnchor).isActive = true
      button.bottomAnchor.constraint(equalTo: _buttonBackgroundView.bottomAnchor).isActive = true
      button.leftAnchor.constraint(equalTo: _buttonBackgroundView.leftAnchor).isActive = true
      button.rightAnchor.constraint(equalTo: _buttonBackgroundView.rightAnchor).isActive = true
      
      let fadeSelector = #selector(IncFormPickerSelectionCell._fadePickerButton)
      button.addTarget(self, action: fadeSelector, for: .touchDown)
      button.addTarget(self, action: fadeSelector, for: .touchDragEnter)
      let unfadeSelector = #selector(IncFormPickerSelectionCell._unfadePickerButton)
      button.addTarget(self, action: unfadeSelector, for: .touchDragExit)
      button.addTarget(self, action: unfadeSelector, for: .touchCancel)
      let touchUpSelector = #selector(IncFormPickerSelectionCell._pickerButtonTouchUpInside)
      button.addTarget(self, action: touchUpSelector, for: .touchUpInside)
      
      _pickerBackgroundView.layer.cornerRadius = 6.0
   }
   
   override func configure(with component: IncFormElemental) {
      guard let element = component as? IncFormPickerSelection else { fatalError() }
      super.configure(with: component)
      let content = element.content
      let config = element.configuration
      if let layoutDelegate = config.layoutDelegate {
         self.layoutDelegate = layoutDelegate
      }
      
      _nameLabel.text = content.name
      _detailLabel.text = content.detail
      _nameLabel.font = config.nameStyle.font
      _buttonBackgroundView.backgroundColor = config.buttonBackgroundColor
      _detailLabel.font = config.detailStyle?.font
      _nameLabel.textColor = config.nameStyle.color
      _detailLabel.textColor = config.detailStyle?.color
      _nameVerticalSpaceConstraint.constant = content.name != nil ? 10 : 0
      _detailVerticalSpaceConstraint.constant = content.detail != nil ? 10 : 0
      _buttonHeightConstraint.constant = config.buttonHeight
      
      _options = element.content.options.map { return (option: $0, dataValue: IncFormElementCell.dataValue($0.value)) }
      guard Set(_options.map { return $0.dataValue }).count == _options.count else { fatalError() }

      _pickerBackgroundView.backgroundColor = config.buttonBackgroundColor
      _pickerView.reloadAllComponents()

      _selectedValue = _selectedOption?.value
      
      _updateIndicatorColor()
      _updateAccessoryImages(with: element)
      
      let angle = element.inputState == .focused ? CGFloat(M_PI) : 0.0
      _rightAccessoryImageView.transform = CGAffineTransform(rotationAngle: angle)
   }
   
   override class func contentSize(for element: IncFormElemental, constrainedWidth width: CGFloat) -> CGSize {
      guard let element = element as? IncFormPickerSelection else { fatalError() }
      let content = element.content
      let config = element.configuration
      let finalWidth = config.width ?? width
      
      guard config.height == nil else {
         return CGSize(width: finalWidth, height: config.height!)
      }
      
      let nameHeight = content.name?.heightWithConstrainedWidth(width: width, font: config.nameStyle.font) ?? 0
      let namePadding: CGFloat = content.name != nil ? 10 : 0
      let pickerHeight: CGFloat = element.inputState == .focused ? 216 : 0
{'fraction_non_alphanumeric': 0.07913832199546485, 'fraction_numerical': 0.0051398337112622825, 'mean_word_length': 3.3408792650918637, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2010550', 'n_tokens_mistral': 3598, 'n_tokens_neox': 3482, 'n_words': 823}