<commit_before>//
// Created by hayato.iida on 2016/09/16.
// Copyright (c) 2016 Speee, Inc. All rights reserved.
//

import Foundation


extension PropertySchema {
  var propertyKey: String {
    get {
      return title ?? ref!.components(separatedBy: "/").last!
    }
  }
}


extension TypeSchema {

  func nullable(_ required: Bool) -> Bool {
    if !required {
      return true
    }
    if let oneOf = self.oneOf {
      //OneOf
      return !oneOf.filter {
        $0.type!.contains(.null)
        }.isEmpty
    } else if self.enumValues != nil {
      return false
    } else if let type = self.type {
      assert(type.count <= 2, "propertySchema.type.count > 2")
      return type.contains(.null)
    } else {
      assertionFailure("property  \(title) cant convert to Type")
    }
    return false
  }

  /// - return: "String","Bool","UserEntity"
  func typeCode(_ propertyName: String = "") -> String {
    return self.codeParseOneOf(propertyName, block: codeTypeBy)
  }

  func typeInnerCode(_ propertyName: String = "") -> String {
    return self.codeParseOneOf(propertyName, block: codeInnerTypeBy)
  }

  func mappingCode(_ propertyName: String, required: Bool) -> String {
    return self.codeParseOneOf(propertyName, block: codeMappingBy(required))
  }

  func serializedCode(_ propertyName: String, required: Bool) -> String {
    return self.codeParseOneOf(propertyName, block: codeSerializedBy(required))
  }

  func enumDefinitionCode(_ propertyName: String) -> String {
    return self.codeParseOneOf(propertyName, block: codeEnumsDeclare)
  }

  func responseEntityCode(_ propertyName: String = "") -> String {
    return self.codeParseOneOf(propertyName, block: responseEntity)
  }


  fileprivate func codeParseOneOf(_ propertyName: String, block: (_ schema: TypeSchema, _ propertyName: String, _ type: ConcreteType) -> String) -> String {
    if let oneOf = self.oneOf {
      return  oneOf.flatMap {
        return $0.type!.first == .null ? nil : $0
      }.first!.codeTypeString(propertyName, block: block)
    } else if self.enumValues != nil {
    }
    return self.codeTypeString(propertyName, block: block)
  }

  fileprivate func codeTypeString(_ propertyName: String, block: (_ schema: TypeSchema, _ propertyName: String, _ type: ConcreteType) -> String) -> String {
    if let type = self.type {
      assert(type.count <= 2, "propertySchema.type.count > 2")
      let typeNotNull = type.filter {
        $0 != .null
      }.first
      if let type = typeNotNull {
        return block(self, propertyName, type)
      }
    }
    return ""
  }

  fileprivate func codeInnerTypeBy(_ schema: TypeSchema, propertyName: String, type: ConcreteType) -> String {
    switch type {
    case .null:
      return ""
    case .array:
      return "\(schema.items!.typeCode())"
    case .object:
        return "\((schema.title ?? propertyName).snake2Camel )" + "Entity"
    case .boolean:
      return "Bool"
    case .integer:
      return "Int"
    case .number:
      return "Double"
    case .string:
      if let format = self.format, format == "date-time" {
        return "Date"
      } else if (schema.media) != nil {
        return "Image"
      } else {
        return "String"
      }
    }
  }

  fileprivate func codeTypeBy(_ schema: TypeSchema, propertyName: String, type: ConcreteType) -> String {
    //FIXME
    if (schema.enumDescription) != nil {
      return propertyName.snake2Camel
    }
    switch type {
    case .array:
      return "[\(codeInnerTypeBy(schema, propertyName: propertyName, type: type))]"
    default:
      return codeInnerTypeBy(schema, propertyName: propertyName, type: type)
    }
  }

  fileprivate func codeMappingBy(_ required: Bool) -> ((TypeSchema, String, ConcreteType) -> String) {
    return { (_ schema: TypeSchema, propertyName: String, type: ConcreteType) in
      //FIXME
      if (schema.enumDescription) != nil {
        return "    self.\(propertyName.snake2camel) = \(propertyName.snake2Camel)(rawValue: json[\"\(propertyName)\"].\(self.rawValue(type: type))!)!" + n
      }
      switch type {
      case .null:
        return ""
      case .array:
        let nullCheck = self.nullable(required) ? "?" : ""
        return "    self.\(propertyName.snake2camel) = json[\"\(propertyName)\"].arrayValue.map { \(self.typeInnerCode())(json: $0)! } as\(nullCheck) \(self.typeCode())" + n
      case .object:
        let nullCheck = self.nullable(required) ? "?" : "!"
        return "    self.\(propertyName.snake2camel) = \(self.typeCode())(json: json[\"\(propertyName)\"]) as \(self.typeCode())\(nullCheck)" + n
      case .boolean:
        let nullCheck = self.nullable(required) ? "" : "!"
        return "    self.\(propertyName.snake2camel) = json[\"\(propertyName)\"].\(self.typeCode().snake2camel)\(nullCheck)" + n
      case .integer:
        let nullCheck = self.nullable(required) ? "" : "!"
        return "    self.\(propertyName.snake2camel) = json[\"\(propertyName)\"].\(self.typeCode().snake2camel)\(nullCheck)" + n
      case .number:
        let nullCheck = self.nullable(required) ? "" : "!"
        return "    self.\(propertyName.snake2camel) = json[\"\(propertyName)\"].\(self.typeCode().snake2camel)\(nullCheck)" + n
      case .string:
        let nullCheck = self.nullable(required) ? "" : "!"
        if let format = self.format, format == "date-time" {
          return "    self.\(propertyName.snake2camel) = Date.generateFromAPIFormat(string: json[\"\(propertyName)\"].string)\(nullCheck)" + n
        } else {
          return "    self.\(propertyName.snake2camel) = json[\"\(propertyName)\"].\(self.typeCode().snake2camel)\(nullCheck)" + n
        }
      }
    }
  }

  fileprivate func rawValue(type: ConcreteType)->String{
    switch type {
    case .integer:
      return "Int"
    default:
      return type.rawValue
    }
  }

  fileprivate func responseEntity(_ schema: TypeSchema, propertyName: String, type: ConcreteType) -> String {
    switch type {
    case .array:<commit_msg>fix int rawValue<commit_after>//
// Created by hayato.iida on 2016/09/16.
// Copyright (c) 2016 Speee, Inc. All rights reserved.
//

import Foundation


extension PropertySchema {
  var propertyKey: String {
    get {
      return title ?? ref!.components(separatedBy: "/").last!
    }
  }
}


extension TypeSchema {

  func nullable(_ required: Bool) -> Bool {
    if !required {
      return true
    }
    if let oneOf = self.oneOf {
      //OneOf
      return !oneOf.filter {
        $0.type!.contains(.null)
        }.isEmpty
    } else if self.enumValues != nil {
      return false
    } else if let type = self.type {
      assert(type.count <= 2, "propertySchema.type.count > 2")
      return type.contains(.null)
    } else {
      assertionFailure("property  \(title) cant convert to Type")
    }
    return false
  }

  /// - return: "String","Bool","UserEntity"
  func typeCode(_ propertyName: String = "") -> String {
    return self.codeParseOneOf(propertyName, block: codeTypeBy)
  }

  func typeInnerCode(_ propertyName: String = "") -> String {
    return self.codeParseOneOf(propertyName, block: codeInnerTypeBy)
  }

  func mappingCode(_ propertyName: String, required: Bool) -> String {
    return self.codeParseOneOf(propertyName, block: codeMappingBy(required))
  }

  func serializedCode(_ propertyName: String, required: Bool) -> String {
    return self.codeParseOneOf(propertyName, block: codeSerializedBy(required))
  }

  func enumDefinitionCode(_ propertyName: String) -> String {
    return self.codeParseOneOf(propertyName, block: codeEnumsDeclare)
  }

  func responseEntityCode(_ propertyName: String = "") -> String {
    return self.codeParseOneOf(propertyName, block: responseEntity)
  }


  fileprivate func codeParseOneOf(_ propertyName: String, block: (_ schema: TypeSchema, _ propertyName: String, _ type: ConcreteType) -> String) -> String {
    if let oneOf = self.oneOf {
      return  oneOf.flatMap {
        return $0.type!.first == .null ? nil : $0
      }.first!.codeTypeString(propertyName, block: block)
    } else if self.enumValues != nil {
    }
    return self.codeTypeString(propertyName, block: block)
  }

  fileprivate func codeTypeString(_ propertyName: String, block: (_ schema: TypeSchema, _ propertyName: String, _ type: ConcreteType) -> String) -> String {
    if let type = self.type {
      assert(type.count <= 2, "propertySchema.type.count > 2")
      let typeNotNull = type.filter {
        $0 != .null
      }.first
      if let type = typeNotNull {
        return block(self, propertyName, type)
      }
    }
    return ""
  }

  fileprivate func codeInnerTypeBy(_ schema: TypeSchema, propertyName: String, type: ConcreteType) -> String {
    switch type {
    case .null:
      return ""
    case .array:
      return "\(schema.items!.typeCode())"
    case .object:
        return "\((schema.title ?? propertyName).snake2Camel )" + "Entity"
    case .boolean:
      return "Bool"
    case .integer:
      return "Int"
    case .number:
      return "Double"
    case .string:
      if let format = self.format, format == "date-time" {
        return "Date"
      } else if (schema.media) != nil {
        return "Image"
      } else {
        return "String"
      }
    }
  }

  fileprivate func codeTypeBy(_ schema: TypeSchema, propertyName: String, type: ConcreteType) -> String {
    //FIXME
    if (schema.enumDescription) != nil {
      return propertyName.snake2Camel
    }
    switch type {
    case .array:
      return "[\(codeInnerTypeBy(schema, propertyName: propertyName, type: type))]"
    default:
      return codeInnerTypeBy(schema, propertyName: propertyName, type: type)
    }
  }

  fileprivate func codeMappingBy(_ required: Bool) -> ((TypeSchema, String, ConcreteType) -> String) {
    return { (_ schema: TypeSchema, propertyName: String, type: ConcreteType) in
      //FIXME
      if (schema.enumDescription) != nil {
        return "    self.\(propertyName.snake2camel) = \(propertyName.snake2Camel)(rawValue: json[\"\(propertyName)\"].\(self.rawValue(type: type))!)!" + n
      }
      switch type {
      case .null:
        return ""
      case .array:
        let nullCheck = self.nullable(required) ? "?" : ""
        return "    self.\(propertyName.snake2camel) = json[\"\(propertyName)\"].arrayValue.map { \(self.typeInnerCode())(json: $0)! } as\(nullCheck) \(self.typeCode())" + n
      case .object:
        let nullCheck = self.nullable(required) ? "?" : "!"
        return "    self.\(propertyName.snake2camel) = \(self.typeCode())(json: json[\"\(propertyName)\"]) as \(self.typeCode())\(nullCheck)" + n
      case .boolean:
        let nullCheck = self.nullable(required) ? "" : "!"
        return "    self.\(propertyName.snake2camel) = json[\"\(propertyName)\"].\(self.typeCode().snake2camel)\(nullCheck)" + n
      case .integer:
        let nullCheck = self.nullable(required) ? "" : "!"
        return "    self.\(propertyName.snake2camel) = json[\"\(propertyName)\"].\(self.typeCode().snake2camel)\(nullCheck)" + n
      case .number:
        let nullCheck = self.nullable(required) ? "" : "!"
        return "    self.\(propertyName.snake2camel) = json[\"\(propertyName)\"].\(self.typeCode().snake2camel)\(nullCheck)" + n
      case .string:
        let nullCheck = self.nullable(required) ? "" : "!"
        if let format = self.format, format == "date-time" {
          return "    self.\(propertyName.snake2camel) = Date.generateFromAPIFormat(string: json[\"\(propertyName)\"].string)\(nullCheck)" + n
        } else {
          return "    self.\(propertyName.snake2camel) = json[\"\(propertyName)\"].\(self.typeCode().snake2camel)\(nullCheck)" + n
        }
      }
    }
  }

  fileprivate func rawValue(type: ConcreteType)->String{
    switch type {
    case .integer:
      return "int"
    default:
      return type.rawValue
    }
  }

  fileprivate func responseEntity(_ schema: TypeSchema, propertyName: String, type: ConcreteType) -> String {
    switch type {
    case .array:
{'fraction_non_alphanumeric': 0.14122741277375303, 'fraction_numerical': 0.005995503372470647, 'mean_word_length': 2.770800627943485, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 41, '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': '6264237', 'n_tokens_mistral': 3742, 'n_tokens_neox': 3619, 'n_words': 853}