class EasyCalendarController < ApplicationController
  accept_rss_auth :user_availability
  accept_api_auth :user_availability

  before_action :authorize_global, :only => [:index, :edit_page_layout, :feed]
  before_action :parse_date_limits, :except => [:save_availability, :index, :edit_page_layout]

  def index
    render_action_as_easy_page(EasyPage.find_by(page_name: 'easy-calendar-module'), nil, nil, easy_calendar_path(t: params[:t]), false, {params: params, page_editable: User.current.allowed_to_globally?(:edit_easy_calendar_layout)})
  end

  def edit_page_layout
    render_action_as_easy_page(EasyPage.find_by(page_name: 'easy-calendar-module'), nil, nil, easy_calendar_path(t: params[:t]), true)
  end

  def feed
    settings = if params[:module_id].present? && (@module = EasyPageZoneModule.find_by(uuid: params[:module_id]))
                 @module.settings
               elsif User.current.logged? && User.current.pref[:easy_calendar]
                 User.current.pref[:easy_calendar]
               else
                 {enabled_calendars: ['easy_meeting_calendar']}
               end

    @events = if @start_date && @end_date
                EasyCalendar::AdvancedCalendar.events(@start_date, @end_date, settings)
              else
                []
              end
    respond_to do |format|
      format.json do
        render json: @events.collect { |e| Hash[e.map { |k, v| [k.to_s.camelcase(:lower), v] }] }
      end
    end
  end

  def project_meetings
    @module = EasyPageZoneModule.find(params[:module_id])

    @project = Project.find(params[:project_id])

    if @start_date && @end_date
      @events = EasyCalendar::AdvancedCalendar.project_events(@start_date, @end_date, @project, @module.settings)
    else
      @events = []
    end

    respond_to do |format|
      format.json { render :json => @events.collect { |e| Hash[e.map { |k, v| [k.to_s.camelcase(:lower), v] }] } }
    end
  end

  def room_meetings
    @room = EasyRoom.find(params[:room_id])

    if @start_date && @end_date
      @events = EasyCalendar::AdvancedCalendar.room_events(@start_date, @end_date, @room)
    else
      @events = []
    end

    respond_to do |format|
      format.json { render :json => @events.collect { |e| Hash[e.map { |k, v| [k.to_s.camelcase(:lower), v] }] } }
    end
  end

  def get_ics
    @user = User.find(params[:user_id]) if params[:user_id].present?
    @user = nil if @user == User.current
    @link = easy_calendar_ics_url({:user_id => @user, :key => User.current.api_key, :format => 'ics'})
    @easy_qr = EasyQr.generate_qr(@link)
    respond_to do |format|
      format.js
      format.html
    end
  end

  def user_availability
    @user = User.find(params[:user_id]) if params[:user_id]
    @user ||= User.current
    events = []

    meetings = EasyMeeting.arel_table
    if request.format == :ics
      includes = [:easy_room, {:author => :email_address}, {:easy_invitations => {:user => :email_address}}]
    else
      includes = [:easy_room, :easy_invitations]
    end
    invitations = EasyMeeting.includes(includes).where(:easy_invitations => {:user_id => @user.id, :accepted => [true, nil]})
    invitations = invitations.where(meetings[:start_time].lt(@end_date)).where(meetings[:end_time].gt(@start_date)) if @start_date && @end_date
    events.concat(invitations.uniq.to_a)

    if Redmine::Plugin.installed?(:easy_attendances) && User.current.allowed_to?(:view_easy_attendance_other_users, nil, :global => true)
      if request.format == :ics
        includes = [:easy_attendance_activity, {:user => :email_address}]
      else
        includes = [:easy_attendance_activity]
      end
      attendances = @user.easy_attendances.includes(includes).where(:easy_attendance_activities => {:at_work => false})
      attendances = attendances.between(@start_date, @end_date) if @start_date && @end_date
      events.concat(attendances.to_a)
    end

    call_hook(:controller_easy_calendar_action_user_availability_before_map_events, {:events => events, :user => @user, :start_date => @start_date, :end_date => @end_date})

    respond_to do |format|
      format.json do
        events.map! do |event|
          is_author = event.is_a?(EasyMeeting) && (User.current.admin? || (event.author_id == User.current.id))
          is_viewable_meeting = event.is_a?(EasyMeeting) && User.current.allowed_to?(:view_all_meetings_detail, nil, :global => true)
          calendar_event = EasyCalendarEvent.create(event)
          result =
              {
                  id: is_author ? "easy_meeting-#{event.id}" : calendar_event.uid,
                  title: calendar_event.title,
                  event_type: is_author ? 'meeting' : (is_viewable_meeting ? 'meeting_detail' : 'availability_meeting'),
                  start: User.current.user_time_in_zone(calendar_event.starts_at).iso8601,
                  end: User.current.user_time_in_zone(calendar_event.ends_at).iso8601,
                  all_day: calendar_event.all_day?,
                  editable: is_author
              }
          if is_author || is_viewable_meeting
            result.merge!(
                {
                    :url => easy_meeting_path(event),
                    :location => event.easy_room.try(:name)
                }
            )
          end
          result
        end

        events.map! { |e| Hash[e.map { |k, v| [k.to_s.camelcase(:lower), v] }] }

        render :json => events
      end
      format.ics do
        icalendar = Icalendar::Calendar.new
        events.each { |evt| icalendar.add_event(EasyCalendarEvent.create(evt).to_ical) }
        render text: icalendar.to_ical
      end
    end
  end

  def save_availability
    if (@module = EasyPageZoneModule.find_by(uuid: params[:module_id]))
      @module.settings ||= {}
      @module.settings[:user_ids] = params[:user_ids] ? params[:user_ids].collect(&:to_i) : []
      @module.save
    elsif User.current.logged?
      settings = User.current.pref[:easy_calendar]
      settings ||= {}
      settings[:user_ids] = params[:user_ids] ? params[:user_ids].collect(&:to_i) : []
      User.current.pref[:easy_calendar] = settings
      User.current.pref.save
    end
    render_api_ok
  end

  def save_calendars
    if (@module = EasyPageZoneModule.find_by(uuid: params[:module_id]))
      @module.settings ||= {}
      @module.settings[:enabled_calendars] = params[:calendar_ids] ? params[:calendar_ids] : []
      @module.save
    elsif User.current.logged?
      settings = User.current.pref[:easy_calendar]
      settings ||= {}
      settings[:enabled_calendars] = params[:calendar_ids] ? params[:calendar_ids] : []
      User.current.pref[:easy_calendar] = settings
      User.current.pref.save
    end
    render_api_ok
  end

  def find_by_worker
    scope = User.active.non_system_flag.easy_type_internal.sorted
    scope = scope.like(params[:q]) unless params[:q].blank?
    @users = scope.to_a

    respond_to do |format|
      format.html { render :partial => 'find_by_worker_list', :locals => {:users => @users} }
      format.js
    end
  end

  def show
    @settings = User.current.pref[:easy_calendar] if User.current.logged?
    @settings ||= {}
    @settings[:display_from] ||= 6
    @settings[:default_view] ||= 'agendaWeek'
    @settings[:default_view] = 'agendaWeek' if is_mobile_device?
    @settings[:default_column_format] = { month: 'ddd' } if is_mobile_device?
    @users = User.where(id: @settings[:user_ids])
    respond_to do |format|
      format.html
      format.js
    end
  end

  private

  def parse_date_limits
    @start_date = DateTime.strptime(params[:start], '%s').to_time rescue nil
    @end_date = DateTime.strptime(params[:end], '%s').to_time rescue nil
  rescue ArgumentError
  end

end
