<NME> UIKitRenderer.swift
<BEF> //
//  UIKitRenderer.swift
//  TemplateKit
//
//  Created by Matias Cudich on 9/3/16.
//  Copyright © 2016 Matias Cudich. All rights reserved.
//

import Foundation

public enum ElementType: ElementRepresentable {
  case box
  case button
  case text
  case textField
  case image
  case table
  case collection
  case activityIndicator
  public func make(_ element: Element, _ owner: Node?) -> Node {
    switch self {
    case .box:
      return NativeNode<Box>(element: element, properties: BaseProperties(element.properties), children: element.children?.map { $0.build(with: owner) }, owner: owner)
    case .button:
      return NativeNode<Button>(element: element, properties: ButtonProperties(element.properties), owner: owner)
    case .text:
      return NativeNode<Text>(element: element, properties: TextProperties(element.properties), owner: owner)
    case .textField:
      return NativeNode<TextField>(element: element, properties: TextFieldProperties(element.properties), owner: owner)
    case .image:
      return NativeNode<Image>(element: element, properties: ImageProperties(element.properties), owner: owner)
    case .view(let view):
      return ViewNode(view: view, element: element, properties: BaseProperties(element.properties), owner: owner)
    case .component(let ComponentType as Node.Type):
      return ComponentType.init(element: element, properties: element.properties, children: nil, owner: owner)
    default:
      fatalError("Unknown element type")
    }
    case .activityIndicator:
      return "activityindicator"
    case .component(let ComponentType):
      return "\(ComponentType)"
    default:
    }
    return self == otherType
  }

  static func fromRaw(_ rawValue: String) throws -> ElementType {
    switch rawValue {
    case "box":
      return .box
    case "button":
      return .button
    case "text":
      return .text
    case "textfield":
      return .textField
    case "image":
      return .image
    default:
      return try .component(NodeRegistry.shared.componentType(for: rawValue))
    }
  }
}

public func ==(lhs: ElementType, rhs: ElementType) -> Bool {
    case (.box, let element as ElementData<Box.PropertiesType>):
      return NativeNode<Box>(element: element, children: element.children?.map { $0.build(withOwner: owner, context: nil) }, owner: owner, context: context)
    case (.text, let element as ElementData<Text.PropertiesType>):
      return NativeNode<Text>(element: element, owner: owner, context: context)
    case (.textField, let element as ElementData<TextField.PropertiesType>):
      return NativeNode<TextField>(element: element, owner: owner, context: context)
    case (.image, let element as ElementData<Image.PropertiesType>):
      return NativeNode<Image>(element: element, owner: owner, context: context)
    case (.button, _):
      return Button(element: element, children: nil, owner: owner, context: context)
    case (.table, let element as ElementData<TableProperties>):
      return Table(element: element, children: nil, owner: owner, context: context)
    case (.collection, let element as ElementData<CollectionProperties>):
      return Collection(element: element, children: nil, owner: owner, context: context)
    case (.activityIndicator, let element as ElementData<ActivityIndicator.PropertiesType>):
      return NativeNode<ActivityIndicator>(element: element, owner: owner, context: context)
    case (.view(let view), let element as ElementData<DefaultProperties>):
      return ViewNode(view: view, element: element, owner: owner, context: context)
    case (.component(let ComponentType), _):
      return ComponentType.init(element: element, children: nil, owner: owner, context: context)
    default:
      fatalError("Supplied element \(element) does not match type \(self)")
    }
  }

  public func equals(_ other: ElementRepresentable) -> Bool {
    guard let otherType = other as? ElementType else {
      return false
    }
    return self == otherType
  }
}

public func ==(lhs: ElementType, rhs: ElementType) -> Bool {
  switch (lhs, rhs) {
  case (.box, .box), (.button, .button), (.text, .text), (.image, .image), (.textField, .textField), (.table, .table), (.activityIndicator, .activityIndicator), (.collection, .collection):
    return true
  case (.view(let lhsView), .view(let rhsView)):
    return lhsView === rhsView
  case (.component(let lhsClass), .component(let rhsClass)):
    return lhsClass == rhsClass
  default:
    return false
  }
}

class DefaultContext: Context {
  let templateService: TemplateService = XMLTemplateService()
  let updateQueue: DispatchQueue = DispatchQueue(label: "UIKitRenderer")
}

public class UIKitRenderer: Renderer {
  public typealias ViewType = UIView

  public static let defaultContext: Context = DefaultContext()
}

<MSG> Some progress on removing untyped properties from everything but XML

<DFF> @@ -20,19 +20,19 @@ public enum ElementType: ElementRepresentable {
   public func make(_ element: Element, _ owner: Node?) -> Node {
     switch self {
     case .box:
-      return NativeNode<Box>(element: element, properties: BaseProperties(element.properties), children: element.children?.map { $0.build(with: owner) }, owner: owner)
+      return NativeNode<Box>(element: element as! ElementData<Box.PropertiesType>, children: element.children?.map { $0.build(with: owner, context: nil) }, owner: owner)
     case .button:
-      return NativeNode<Button>(element: element, properties: ButtonProperties(element.properties), owner: owner)
+      return NativeNode<Button>(element: element as! ElementData<Button.PropertiesType>, owner: owner)
     case .text:
-      return NativeNode<Text>(element: element, properties: TextProperties(element.properties), owner: owner)
+      return NativeNode<Text>(element: element as! ElementData<Text.PropertiesType>, owner: owner)
     case .textField:
-      return NativeNode<TextField>(element: element, properties: TextFieldProperties(element.properties), owner: owner)
+      return NativeNode<TextField>(element: element as! ElementData<TextField.PropertiesType>, owner: owner)
     case .image:
-      return NativeNode<Image>(element: element, properties: ImageProperties(element.properties), owner: owner)
+      return NativeNode<Image>(element: element as! ElementData<Image.PropertiesType>, owner: owner)
     case .view(let view):
-      return ViewNode(view: view, element: element, properties: BaseProperties(element.properties), owner: owner)
-    case .component(let ComponentType as Node.Type):
-      return ComponentType.init(element: element, properties: element.properties, children: nil, owner: owner)
+      return ViewNode(view: view, element: element as! ElementData<BaseProperties>, owner: owner)
+    case .component(let ComponentType as ComponentCreation.Type):
+      return ComponentType.init(element: element, children: nil, owner: owner)
     default:
       fatalError("Unknown element type")
     }
@@ -44,23 +44,6 @@ public enum ElementType: ElementRepresentable {
     }
     return self == otherType
   }
-
-  static func fromRaw(_ rawValue: String) throws -> ElementType {
-    switch rawValue {
-    case "box":
-      return .box
-    case "button":
-      return .button
-    case "text":
-      return .text
-    case "textfield":
-      return .textField
-    case "image":
-      return .image
-    default:
-      return try .component(NodeRegistry.shared.componentType(for: rawValue))
-    }
-  }
 }
 
 public func ==(lhs: ElementType, rhs: ElementType) -> Bool {

Some progress on removing untyped properties from everything but XML