class MessagesController < ApplicationController
  before_action :set_message, only: [:show, :edit, :update, :destroy]

  # GET /messages
  # GET /messages.json
  def index
    Linguistics.use( :en )
    @messages = Message.all
  end

  # GET /messages/1
  # GET /messages/1.json
  def show
  end

  # GET /messages/new
  def new
    @message = Message.new
  end

  # GET /messages/1/edit
  def edit
  end

  # POST /messages
  # POST /messages.json
  def create
    if (params[:commit] == "Remove messages")
      clean_all_messages
      respond_to do |format|
        format.html { redirect_to :back }
      end
    elsif (!params[:email_account].nil?)
      if (params[:email_folder] == "" || params[:email_folder].nil?)
        params[:email_folder] = "Inbox"
      end
      fetch_messages(params[:email_server], params[:email_account], params[:email_password], params[:email_folder])
      #Check for additional security measures?
      respond_to do |format|
        format.html { redirect_to :back }
      end
    else
      @message = Message.new(message_params)
      respond_to do |format|
        if @message.save
          format.html { redirect_to @message, notice: 'Message was successfully created.' }
          format.json { render action: 'show', status: :created, location: @message }
        else
          format.html { render action: 'new' }
          format.json { render json: @message.errors, status: :unprocessable_entity }
        end
      end
    end
  end

  # PATCH/PUT /messages/1
  # PATCH/PUT /messages/1.json
  def update
    @message[:response] = params[:response].join(' ')
    respond_to do |format|
      if @message.update(message_params)
        format.html { redirect_to @message, notice: 'Message was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @message.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /messages/1
  # DELETE /messages/1.json
  def destroy
    @message.destroy
    respond_to do |format|
      format.html { redirect_to messages_url }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_message
      @message = Message.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def message_params
      params.require(:message).permit(:address_id, :subject, :received, :sent, :content, :response)
    end

    # This segment contains code adapted from that found at http://alvinalexander.com/blog/post/ruby/ruby-search-imap-mail-server-using-multiple-search-fields
    def fetch_messages(serverVal, userVal, passVal, folderVal)
      server = serverVal
      user = userVal
      pass = passVal
      folder = folderVal
      port = 993
      imap = Net::IMAP.new(server, port, options = {:ssl => true}, nil, false)
      imap.login(user, pass)
      imap.select(folder)
      debugFile = "/home/elliott/CodeLibraries/reflex-linguist/test/messageControllerTestOutput.txt";
      oF = File.open(debugFile, "w");
      imap.search(["FROM", ""]).each do |msg_id|
=begin
        msg = imap.fetch(msg_id, "(UID RFC822.SIZE ENVELOPE BODY[TEXT])")[0]
        envelope = msg.attr["ENVELOPE"]
        rfcSize = msg.attr["RFC822.SIZE"]
        body = msg.attr["BODY[TEXT]"]
        uid = msg.attr["UID"]
=end
        msg = imap.fetch(msg_id, "(RFC822 ENVELOPE)")[0]
        envelope = msg.attr["ENVELOPE"]
        mail = Mail.new(msg.attr["RFC822"])
#        puts "\n\n\n\n\n" + mail.methods.to_s + "\n\n\n\n\n"
        plaintextMessage = find_plaintext_parts(mail)
#        puts "DIRTY! " + plaintextMessage
        plaintextMessage = clean_plaintext(plaintextMessage)
#        puts "CLEANED! " + plaintextMessage
#        oF << "Location of plaintext of message (if applicable): " + (mail.to_s =~ /Content\-Type\:\ text\/plain;/).to_s
        puts "ENVELOPE: " + envelope.to_s + "\n"
        thisDatePreparsed = envelope.date.to_s
        #Remove parenthesized timezone from the end of the envelope date string
        thisDatePreparsed = thisDatePreparsed.gsub(/\ \([^\)]+\)$/, "")
        thisDatePreparsed = thisDatePreparsed.gsub(/\-0000$/, "+0000")
        thisDate = "[ERROR]"
        if (thisDatePreparsed.nil?)
          thisDatePreparsed = "1 Jan 1960 00:00:00 UTC -07:00"
        else
          log(" DATE: " + thisDatePreparsed.to_s, oF)
          thisDate = Date.rfc2822(thisDatePreparsed)
        end
        #puts "THISdatePREparsed: " + thisDatePreparsed
        log("FROMINFO: A" + envelope.from.to_s + "\n", oF)
        thisFrom = envelope.from[0].mailbox.to_s + "@" + envelope.from[0].host.to_s
        #log("DATE TESTING: " + thisDate.methods.to_s + "\n", oF)
        thisSubject = "<N/A>"
        if (!envelope.subject.nil?)
          log(" SUBJ: " + envelope.subject.to_s, oF)
          thisSubject = envelope.subject.to_s
        end
        if (!envelope.from.nil?)
          log(" FROM: " + envelope.from.to_s, oF)
        end
        log("\n", oF)
#        oF << "\n\n\n/mail:\n\n\n " + mail.to_s + "\n"
        log("\n\n\n/plaintext:\n\n\n " + plaintextMessage.to_s + "\n", oF)
        if (plaintextMessage.nil? || plaintextMessage == "")
          plaintextMessage = "<N/A>"
        end
#{ subject: 'test1', address: Address.find(1), received: (DateTime.civil_from_format :local, 2012), sent: (DateTime.civil_from_format :local, 2013), content: "HEY THERE!!", response: "What!?" }
#{ subject: thisSubject, address: Address.find(1), received: (thisDate), sent: (DateTime.civil_from_format :local, 2013), content: "HEY THERE!!", response: "What!?" }
        log("******////////\n", oF)
        log("FROMINFO B: " + thisFrom, oF)

        nullPerson = Person.find_by(name: "Unknown")
        @address = Address.find_by(email: thisFrom)
        if (!@address.nil?)
          matchingPerson = Person.find(@address.person)
          if (matchingPerson.nil?)
            #this should not occur, since all addresses should already be associated with a person
          else
            #there is nothing extra to do if the person and address are both found 
          end
          @message = Message.new(subject: thisSubject, address: @address, received: (thisDate), sent: (DateTime.civil_from_format :local, 1960), content: plaintextMessage.to_s, response: "<N/A>")
          if (!@message.save)
            log("\n\n WARNING!!! \n Message was not successfully saved. \n\n", oF)
          end
        else
          @address = Address.create!(email: thisFrom, person: nullPerson)
          @address.save
          @message = Message.create!(subject: thisSubject, address: @address, received: (thisDate), sent: (DateTime.civil_from_format :local, 1960), content: plaintextMessage.to_s, response: "<N/A>")
          if (!@message.save)
            log("\n\n WARNING!!! \n Message was not successfully saved. \n\n", oF)
          end
        end
      end
      imap.logout
      imap.disconnect
    end

    helper_method :fetch_messages

    def find_plaintext_parts(mailObject)
      plaintextString = ""
      if (!mailObject.multipart?)
        if (mailObject.content_type =~ /text\/plain/ && !mailObject.to_s.nil? && mailObject.to_s != "" && (mailObject.to_s !~ /^Content\-Disposition\:\ attachment\;/) && (mailObject.to_s !~ /^Content\-Transfer\-Encoding\:\ quoted\-printable/))
          plaintextString += "\n<<MAIL_PART_ENDS>>\n" + mailObject.to_s
        end
      else
        mailObject.parts.each do |thisPart|
          plaintextString += find_plaintext_parts(thisPart)
        end
      end
      return plaintextString
    end

    helper_method :find_plaintext_parts

    def clean_plaintext(plaintext)
      cleanedPlaintext = plaintext.gsub(/\<\<MAIL\_PART\_ENDS\>\>/, "")
      cleanedPlaintext = cleanedPlaintext.gsub(/.*Content\-Transfer\-Encoding\:\ [^\n]*\n/m, "")
      return cleanedPlaintext
    end

    helper_method :clean_plaintext

    def log(content, oF)
      oF << ">>> [LOG]: " + content + "\n"
    end

    helper_method :log

    def clean_all_messages
      Message.destroy_all
    end

end
