<commit_before>/*
 * Copyright 2016 HM Revenue & Customs
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package validation

import java.text.SimpleDateFormat
import java.util.Date

import org.joda.time.LocalDate
import org.joda.time.format.DateTimeFormat
import play.api.i18n.Messages
import services.BulkRequestCsvColumn
import uk.gov.hmrc.time.TaxYear

trait FieldValidator {

  val MAX_NAME_LENGTH = 99
  val DATE_FORMAT_PATTERN = "dd/MM/yyyy"
  val DATE_FORMAT = DateTimeFormat.forPattern(DATE_FORMAT_PATTERN)

  def validateScon(scon: String): Option[String] = {
    scon match {
      case "" => Some(Messages("gmp.error.mandatory", Messages("gmp.scon")))
      case x if !SconValidate.isValid(x) => Some(Messages("gmp.error.scon.bulk.invalid"))
      case _ => None
    }
  }

  def validateNino(nino: String) = {
    val TEMP_NINO = "TN"
    nino match {
      case "" => Some(Messages("gmp.error.mandatory", Messages("gmp.nino")))
      case x if !NinoValidate.isValid(x) => Some(Messages("gmp.error.nino.invalid"))
      case x if x.toUpperCase().startsWith(TEMP_NINO) => Some(Messages("gmp.error.nino.temporary"))
      case _ => None
    }
  }

  def validateFirstName(name: String) = {
    name match {
      case "" => Some(Messages("gmp.error.firstnameorinitial"))
      case x if x.length >= MAX_NAME_LENGTH => Some(Messages("gmp.error.firstname.toolong"))
      case x if !NameValidate.isValid(x) => {
        val message = Messages("gmp.error.name.invalid", Messages("gmp.lowercase.firstname"))
        Some(s""""$message"""")
      }
      case _ => None
    }
  }

  def validateLastName(name: String) = {
    name match {
      case "" => Some(Messages("gmp.error.mandatory", Messages("gmp.lowercase.lastname")))
      case x if x.length >= MAX_NAME_LENGTH => Some(Messages("gmp.error.lastname.toolong"))
      case x if x.length == 1 => Some(Messages("gmp.error.surname.invalid"))
      case x if !NameValidate.isValid(x) => {
        val message = Messages("gmp.error.name.invalid", Messages("gmp.lowercase.lastname"))
        Some(s""""$message"""")
      }
      case _ => None
    }
  }

  def validateCalcType(calcType: String) = {
    calcType match {
      case "" => Some(Messages("gmp.error.calctype.out_of_range"))
      case x if !(x matches """\d+""") => Some(Messages("gmp.error.calctype.invalid"))
      case x if x.toInt > 4 => Some(Messages("gmp.error.calctype.out_of_range"))
      case _ => None
    }
  }

  def validateDate(value: String) = {
    value match {
      case "" => None
      case x if !DateValidate.isValid(value) => Some(Messages("gmp.error.csv.date.invalid"))
      case _ => None
    }
  }

  def validateTerminationDate(value: String) = {

    val validDate = tryParseDate(value)

    value match {
      case "" => None
      case "SM" => None
      case invalidDate if validDate.isEmpty => Some(Messages("gmp.error.csv.termination.invalid"))
      case before2016 if validDate.isDefined && validDate.get.isBefore(TaxYear(2016).starts)
        => Some(Messages("gmp.error.csv.termination.oob"))
      case _ => None
    }
  }

  def validateRevalRate(value: String) = {
    value match {
      case "" => None
      case x if !(x matches """\d+""") => Some(Messages("gmp.error.revaluation_rate.invalid"))
      case x if x.toInt > 3 => Some(Messages("gmp.error.revaluation_rate.invalid"))
      case _ => None
    }
  }

  def validateDualCalc(value: String) = {
    value match {
      case "" => Some(Messages("gmp.error.csv.dual_calc.invalid"))
      case x if !(x matches "(?i)y(es)?|no?") => Some(Messages("gmp.error.csv.dual_calc.invalid"))
      case _ => None
    }
  }

  private def tryParseDate(date: String): Option[LocalDate] =
    if (!DateValidate.isValid(date))
      None
    else
      try {
        Some(LocalDate.parse(date, DATE_FORMAT))
      } catch {
        case e: IllegalArgumentException => None
      }
}

object FieldValidator extends FieldValidator

object CsvLineValidator extends FieldValidator {

  val CSV_COLUMN_COUNT = 10

  def validateLine(line: String) = {
<commit_msg>Removed redundant try/catch around the date parsing<commit_after>/*
 * Copyright 2016 HM Revenue & Customs
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package validation

import java.text.SimpleDateFormat
import java.util.Date

import org.joda.time.LocalDate
import org.joda.time.format.DateTimeFormat
import play.api.i18n.Messages
import services.BulkRequestCsvColumn
import uk.gov.hmrc.time.TaxYear

trait FieldValidator {

  val MAX_NAME_LENGTH = 99
  val DATE_FORMAT_PATTERN = "dd/MM/yyyy"
  val DATE_FORMAT = DateTimeFormat.forPattern(DATE_FORMAT_PATTERN)

  def validateScon(scon: String): Option[String] = {
    scon match {
      case "" => Some(Messages("gmp.error.mandatory", Messages("gmp.scon")))
      case x if !SconValidate.isValid(x) => Some(Messages("gmp.error.scon.bulk.invalid"))
      case _ => None
    }
  }

  def validateNino(nino: String) = {
    val TEMP_NINO = "TN"
    nino match {
      case "" => Some(Messages("gmp.error.mandatory", Messages("gmp.nino")))
      case x if !NinoValidate.isValid(x) => Some(Messages("gmp.error.nino.invalid"))
      case x if x.toUpperCase().startsWith(TEMP_NINO) => Some(Messages("gmp.error.nino.temporary"))
      case _ => None
    }
  }

  def validateFirstName(name: String) = {
    name match {
      case "" => Some(Messages("gmp.error.firstnameorinitial"))
      case x if x.length >= MAX_NAME_LENGTH => Some(Messages("gmp.error.firstname.toolong"))
      case x if !NameValidate.isValid(x) => {
        val message = Messages("gmp.error.name.invalid", Messages("gmp.lowercase.firstname"))
        Some(s""""$message"""")
      }
      case _ => None
    }
  }

  def validateLastName(name: String) = {
    name match {
      case "" => Some(Messages("gmp.error.mandatory", Messages("gmp.lowercase.lastname")))
      case x if x.length >= MAX_NAME_LENGTH => Some(Messages("gmp.error.lastname.toolong"))
      case x if x.length == 1 => Some(Messages("gmp.error.surname.invalid"))
      case x if !NameValidate.isValid(x) => {
        val message = Messages("gmp.error.name.invalid", Messages("gmp.lowercase.lastname"))
        Some(s""""$message"""")
      }
      case _ => None
    }
  }

  def validateCalcType(calcType: String) = {
    calcType match {
      case "" => Some(Messages("gmp.error.calctype.out_of_range"))
      case x if !(x matches """\d+""") => Some(Messages("gmp.error.calctype.invalid"))
      case x if x.toInt > 4 => Some(Messages("gmp.error.calctype.out_of_range"))
      case _ => None
    }
  }

  def validateDate(value: String) = {
    value match {
      case "" => None
      case x if !DateValidate.isValid(value) => Some(Messages("gmp.error.csv.date.invalid"))
      case _ => None
    }
  }

  def validateTerminationDate(value: String) = {

    val validDate = tryParseDate(value)

    value match {
      case "" => None
      case "SM" => None
      case invalidDate if validDate.isEmpty => Some(Messages("gmp.error.csv.termination.invalid"))
      case before2016 if validDate.isDefined && validDate.get.isBefore(TaxYear(2016).starts)
        => Some(Messages("gmp.error.csv.termination.oob"))
      case _ => None
    }
  }

  def validateRevalRate(value: String) = {
    value match {
      case "" => None
      case x if !(x matches """\d+""") => Some(Messages("gmp.error.revaluation_rate.invalid"))
      case x if x.toInt > 3 => Some(Messages("gmp.error.revaluation_rate.invalid"))
      case _ => None
    }
  }

  def validateDualCalc(value: String) = {
    value match {
      case "" => Some(Messages("gmp.error.csv.dual_calc.invalid"))
      case x if !(x matches "(?i)y(es)?|no?") => Some(Messages("gmp.error.csv.dual_calc.invalid"))
      case _ => None
    }
  }

  private def tryParseDate(date: String): Option[LocalDate] =
    if (!DateValidate.isValid(date))
      None
    else
      Some(LocalDate.parse(date, DATE_FORMAT))
}

object FieldValidator extends FieldValidator

object CsvLineValidator extends FieldValidator {

  val CSV_COLUMN_COUNT = 10

  def validateLine(line: String) = {

{'fraction_non_alphanumeric': 0.1357009755562863, 'fraction_numerical': 0.00548065329387263, 'mean_word_length': 3.2536130536130536, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 82, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '5756327', 'n_tokens_mistral': 2980, 'n_tokens_neox': 2904, 'n_words': 672}