_ = require('lodash')
bench = require('../../common/js/bench.coffee')

proposal_filters =
  gates: (proposal, filter_value) ->
    # magic gates have id with minus
    _.contains(filter_value, proposal.gate_id) or _.contains(filter_value, (+proposal.gate_id * -1).toString())

ticket_filters =

  tour_ticket: (ticket, filter_value) -> !filter_value or ticket.hotel?

  stops_count: (ticket, filter_value) ->
    ticket.max_stops in filter_value

  max_stop_duration: (ticket, filter_value) ->
    return true if ticket.max_stop_duration == 0
    ticket.max_stop_duration <= filter_value

  min_stop_duration: (ticket, filter_value) ->
    return true if !ticket.min_stop_duration
    ticket.min_stop_duration >= filter_value

  segments_time: (ticket, filter_value) ->
    for index in filter_value
      [filter_departure_time, filter_arrival_time] = filter_value[index]
      [ticket_departure_time, ticket_arrival_time] = ticket.segments_time[index]
      if ticket_departure_time < filter_departure_time
        return false
      if ticket_arrival_time > filter_arrival_time
        return false
    true

  segments_airports: (ticket, filter_value) ->
    for index in filter_value
      [filter_departure_list, filter_arrival_list] = filter_value[index]
      [ticket_departure, ticket_arrival] = ticket.segments_airports[index]
      return false if !_.contains(filter_departure_list, ticket_departure)
      return false if !_.contains(filter_arrival_list, ticket_arrival)
    true

  departure_airports: (ticket, filter_value) ->
    departure_airports_list = [ticket.segments_airports[0][0]]
    if ticket.segments_airports.length > 1 and ticket.segments_airports[0][0] != ticket.segments_airports[1][1]
      departure_airports_list.push(ticket.segments_airports[1][1])
    _.intersection(departure_airports_list, filter_value).length == departure_airports_list.length

  arrival_airports: (ticket, filter_value) ->
    departure_airports_list = [ticket.segments_airports[0][1]]
    if ticket.segments_airports.length > 1 and ticket.segments_airports[0][1] != ticket.segments_airports[1][0]
      departure_airports_list.push(ticket.segments_airports[1][0])
    _.intersection(departure_airports_list, filter_value).length == departure_airports_list.length

  _flight_time_filter: (ticket, filter_value, segment, direction) ->
    direction_hash = {
      departure: 0
      arrival: ticket.segment[segment].flight.length - 1
    }
    ticket.segment[segment].flight[direction_hash[direction]]["#{direction}_time"] >= filter_value[0] and
    ticket.segment[segment].flight[direction_hash[direction]]["#{direction}_time"] <= filter_value[1]

  _filter_arrival_datetime: (ticket, filter_value, segment) ->
    flight_index = ticket.segment[segment].flight.length - 1
#    console.log '_filter_arrival_datetime', segment, new Date(filter_value[0] * 1000), new Date(filter_value[1] * 1000), new Date(1000* ticket.segment[segment].flight[flight_index]["local_arrival_timestamp"])
    ticket.segment[segment].flight[flight_index]["local_arrival_timestamp"] >= filter_value[0] and
    ticket.segment[segment].flight[flight_index]["local_arrival_timestamp"] <= filter_value[1]

  departure_time_0: (ticket, filter_value) ->
    @_flight_time_filter(ticket, filter_value, 0, 'departure')

  departure_time_1: (ticket, filter_value) ->
    @_flight_time_filter(ticket, filter_value, 1, 'departure')

  arrival_datetime_0: (ticket, filter_value) ->
    @_filter_arrival_datetime(ticket, filter_value, 0)

  arrival_datetime_1: (ticket, filter_value) ->
    @_filter_arrival_datetime(ticket, filter_value, 1)

  airlines: (ticket, filter_value) ->
    validating_carrier =  ticket.validating_carrier
    _.contains(filter_value, validating_carrier)

  show_only_best: (ticket, filter_value) ->
    filter_value == false or ticket.best != 'hidden'

# speed is around 0.1ms
smart_clone = (tickets) -> _.map(tickets, (ticket) -> [ticket[0], _.clone(ticket[1])])

filter = bench('filter', ((tickets, filters_state) ->
  _.filter(smart_clone(tickets), (ticket) ->
    ticket[1] = _.filter(ticket[1], (proposal) ->
      for name, filter_value of filters_state
        continue if _.isNull(filter_value) or !proposal_filters[name]
        if(!proposal_filters[name](proposal, filter_value))
          return false
      true
    )

    return false if _.isEmpty(ticket[1])
    for name, filter_value of filters_state
      continue if _.isNull(filter_value) or !ticket_filters[name]
      if(!ticket_filters[name](ticket[0], filter_value))
        return false
    true
  )), {tickets: (args) -> args[0].length} )

module.exports = {
  filter: filter
}
