// Copyright (C) 2017 The Android Open Source Project
//
// 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 com.googlesource.gerrit.plugins.analytics.wizard.model

import java.net.URL
import java.time.LocalDate
import java.time.format.DateTimeFormatter

import enumeratum.EnumEntry.Snakecase
import enumeratum._

import scala.util.{Failure, Success, Try}

case class ETLConfig(aggregate: AggregationType,
                     projectPrefix: Option[String],
                     since: Option[LocalDate],
                     until: Option[LocalDate],
                     eventsUrl: Option[URL],
                     writeNotProcessedEventsTo: Option[URL],
                     emailAliasesPath: Option[String],
                     username: Option[String],
                     password: Option[String])

sealed trait AggregationType extends EnumEntry with Snakecase
object AggregationType extends Enum[AggregationType] {
  val values = findValues

  case object Email      extends AggregationType
  case object EmailHour  extends AggregationType
  case object EmailDay   extends AggregationType
  case object EmailMonth extends AggregationType
  case object EmailYear  extends AggregationType
}

object ETLConfig {
  def fromRaw(raw: ETLConfigRaw): Either[ETLConfigValidationError, ETLConfig] = {
    for {
      s  <- validateLocalDate("since", raw.since).right
      u  <- validateLocalDate("until", raw.until).right
      w  <- validateUrl("writeNotProcessedEventsTo", raw.writeNotProcessedEventsTo).right
      eu <- validateUrl("eventsUrl", raw.eventsUrl).right
      a  <- validateAggregate(raw.aggregate).right
    } yield
      ETLConfig(
        aggregate = a,
        projectPrefix = Option(raw.projectPrefix),
        since = s,
        until = u,
        eventsUrl = eu,
        writeNotProcessedEventsTo = w,
        emailAliasesPath = Option(raw.emailAliasesPath),
        username = Option(raw.username),
        password = Option(raw.password)
      )
  }

  private def validateLocalDate(
      parameter: String,
      value: String): Either[LocalDateValidationError, Option[LocalDate]] = {
    val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")

    Option(value)
      .map { maybeDate =>
        Try(LocalDate.parse(maybeDate, formatter)) match {
          case Success(date)      => Right(Some(date))
          case Failure(exception) => Left(LocalDateValidationError(parameter, maybeDate, exception))
        }
      }
      .getOrElse(Right(None))
  }
  private def validateUrl(parameter: String,
                          value: String): Either[UrlValidationError, Option[URL]] = {
    Option(value)
      .map { u =>
        Try(new URL(u)) match {
          case Success(url)       => Right(Some(url))
          case Failure(exception) => Left(UrlValidationError(parameter, u, exception))
        }
      }
      .getOrElse(Right(None))
  }
  private def validateAggregate(
      value: String): Either[AggregateValidationError, AggregationType] = {
    val maybeAggregate =
      AggregationType.withNameInsensitiveOption(Option(value).getOrElse("email"))
    Either.cond(maybeAggregate.isDefined, maybeAggregate.get, AggregateValidationError(value))
  }
}

sealed trait ETLConfigValidationError {
  def message: String = s"Error validating '$parameter' parameter: $value. Exception: $cause"
  def value: String
  def parameter: String
  def cause: Throwable
}
case class LocalDateValidationError(parameter: String, value: String, cause: Throwable)
    extends ETLConfigValidationError
case class UrlValidationError(parameter: String, value: String, cause: Throwable)
    extends ETLConfigValidationError
case class AggregateValidationError(value: String) extends ETLConfigValidationError {
  val parameter        = "aggregate"
  val cause: Throwable = new Throwable(s"Value $value is not a valid aggregation type")
}
