# -*- coding: utf-8 -*-
require 'spec_helper'
describe APN::Notification do

  let(:token) { "2589b1aa 363d23d8 d7f16695 1a9e3ff4 1fb0130a 637d6997 a2080d88 1b2a19b5" }
  let(:payload) {"fake"}
  let(:notification) do
    APN::Notification.new(token, payload)
  end

  describe ".packaged_message" do

    let(:message) do
      notification.packaged_message
    end

    context "when payload is a string" do
      let(:payload) { "hi" }

      it "adds 'aps' key" do
        expect(ActiveSupport::JSON::decode(message)).to have_key('aps')
      end

      it "encode the payload" do
        expect(message)
          .to eq(ActiveSupport::JSON::encode(aps: {alert: payload}))
      end
    end

    context "when payload is a hash" do
      let(:payload) do
        {alert: 'paylod'}
      end

      it "adds 'aps' key" do
        expect(ActiveSupport::JSON::decode(message)).to have_key('aps')
      end

      it "encode the payload" do
        expect(message)
          .to eq(ActiveSupport::JSON::encode(aps: payload))
      end
    end

    context "when payload is over 2048 bytes" do
      let(:payload) { "»" * 2049 }

      it "raises" do
        expect {
          notification.packaged_message
        }.to raise_error
      end
    end

    [1, true].each do |v|
      context "when content_available is #{v}" do
        let(:payload) do
          {content_available: v}
        end

        it "adds to the message" do
          expect(message)
            .to eq(ActiveSupport::JSON::encode(aps: {'content-available' => 1}))
        end
      end
    end

    context "when payload is Localizable" do
      pending
    end
  end

  describe ".packaged_token" do

    context "when is a valid token" do

      it "has 32 byte size" do
        expect(notification.packaged_token.bytesize).to eq(32)
      end
    end

    context "when token doesnt have spaces" do
      let(:token) { "2589b1aa363d23d8d7f166951a9e3ff41fb0130a637d6997a2080d881b2a19b5" }

      it "has 32 byte size" do
        expect(notification.packaged_token.bytesize).to eq(32)
      end
    end

    context "when token is more that 32 bytes" do
      let(:token) { "9b1e2" * 50 }

      it "raises" do
        pending
      end
    end
  end

  describe ".packaged_notification" do
    it 'has the correct size' do
      size = 1 + # command
             4 + # frame_length
             35 + # token_frame
             27 # payload_frame
      expect(notification.packaged_notification.bytesize).to eq(size)
    end

    it 'has the correct format' do
      packaged = "\x02\x00\x00\x00\x3e" +
        "\x01\x00\x20#{notification.packaged_token}" +
        "\x02\x00\x18#{notification.packaged_message}"
      expect(notification.packaged_notification).to eq(packaged)
    end
  end

  describe ".truncate_alert!" do

    before do
      APN.truncate_alert = true
    end
    after do
      APN.truncate_alert = false
    end

    context "when alert is a string" do
      let(:payload) { "a" * 2049 }

      it "truncates the alert" do
        expect(notification.packaged_message.size.to_i).to eq(APN::Notification::DATA_MAX_BYTES)
      end

      it "has payload size equals payload byte size" do
        expect(notification.packaged_message.size.to_i).to eq(notification.payload_size)
      end

      it "has payload truncated only the alert" do
        expect(notification.packaged_message).to eq({aps:{alert: "a" * 2027 }}.to_json)
      end
    end

    context "when payload is a hash" do
      let(:payload) do
        { alert: { 'loc-args' => ["a" * 2049] }}
      end

      it "truncates the alert" do
        expect(notification.packaged_message.size.to_i).to eq(APN::Notification::DATA_MAX_BYTES)
      end

      it "has payload size equals payload byte size" do
        expect(notification.packaged_message.size.to_i).to eq(notification.payload_size)
      end
    end

    context "when payload is multibyte string" do
      let(:payload) { "»" * 2048 }

      it "truncates the alert in a way that no multibyte character gets truncated " do
        expect(notification.payload_size).to eq(APN::Notification::DATA_MAX_BYTES - 1)
      end

      if ActiveSupport::VERSION::MAJOR == 4
        it "has different payload size and message size" do
          expect(notification.packaged_message.size.to_i).to_not eq(notification.payload_size)
        end
      elsif ActiveSupport::VERSION::MAJOR == 3
        it "has the same payload size and message size" do
          expect(notification.packaged_message.size.to_i).to eq(notification.payload_size)
        end
      end
    end
  end
end
