module Deliver  
  # Everything related to submitting the app
  class ItunesConnect
    
    # This will put the latest uploaded build as a new beta build
    def put_build_into_beta_testing!(app, version_number)
      begin
        verify_app(app)
        open_app_page(app)

        Helper.log.info("Choosing the latest build on iTunesConnect for beta distribution")

        sleep 3
        click_on "Prerelease"
        sleep 3

        wait_for_preprocessing

        # Beta Switches
        if all(".switcher.ng-binding.checked").count == 0
          raise "Looks like Beta Testing is not yet enabled for this app. Open '#{current_url}' and enable TestFlight Beta Testing.".red
        end
        
        if all(".bt-version > a").count == 0
          raise "Couldn't find any builds. Please check the iTunes Conncet page: '#{current_url}'".red
        end

        first(".bt-version > a").click

        email = wait_for_elements("input[ng-model='testinfo.data.details[currentLoc].feedbackEmail.value']").first
        if email.value.to_s.length == 0
          # Some value is needed to actually distribute the beta version
          email.set CredentialsManager::PasswordManager.shared_manager.username
          click_on "Save"
        end

        Helper.log.info "Successfully enabled latest beta build.".green

        return true
      rescue => ex
        error_occured(ex)
      end
    end

    # This will choose the latest uploaded build on iTunesConnect as the production one
    # After this method, you still have to call submit_for_review to actually submit the
    # whole update
    # @param app (Deliver::App) the app you want to choose the build for
    # @param version_number (String) the version number as string for 
    def put_build_into_production!(app, version_number)
      begin
        verify_app(app)
        open_app_page(app)

        Helper.log.info("Choosing the latest build on iTunesConnect for release")

        click_on "Prerelease"

        wait_for_preprocessing

        ################# Apple is finished processing the ipa file #################

        Helper.log.info("Apple finally finished processing the ipa file")
        open_app_page(app)

        begin
          first('a', :text => BUTTON_ADD_NEW_BUILD).click
          wait_for_elements(".buildModalList")
          sleep 5
        rescue
          if page.has_content?"Upload Date"
            # That's fine, the ipa was already selected
            return true
          else
            raise "Could not find Build Button. It looks like the ipa file was not properly uploaded."
          end
        end

        if page.all('td', :text => version_number).count > 1
          Helper.log.fatal "There were multiple submitted builds found. Don't know which one to choose. Just choosing the top one for now"
        end

        result = page.first('td', :text => version_number).first(:xpath,"./..").first(:css, ".small").click
        click_on "Done" # Save the modal dialog
        click_on "Save" # on the top right to save everything else

        error = page.has_content?BUTTON_ADD_NEW_BUILD
        raise "Could not put build itself onto production. Try opening '#{current_url}'" if error

        return true
      rescue => ex
        error_occured(ex)
      end
    end

    # Submits the update itself to Apple, this includes the app metadata and the ipa file
    # This can easily cause exceptions, which will be shown on iTC.
    # @param app (Deliver::App) the app you want to submit
    # @param perms (Hash) information about content rights, ...
    def submit_for_review!(app, perms = nil)
      begin
        verify_app(app)
        open_app_page(app)

        Helper.log.info("Submitting app for Review")

        if not page.has_content?BUTTON_STRING_SUBMIT_FOR_REVIEW
          if page.has_content?WAITING_FOR_REVIEW
            Helper.log.info("App is already Waiting For Review")
            return true
          else
            raise "Couldn't find button with name '#{BUTTON_STRING_SUBMIT_FOR_REVIEW}'!"
          end
        end

        click_on BUTTON_STRING_SUBMIT_FOR_REVIEW
        sleep 4

        errors = (all(".pagemessage.error") || []).count > 0
        raise "Some error occured when submitting the app for review: '#{current_url}'" if errors

        wait_for_elements(".savingWrapper.ng-scope.ng-pristine")
        wait_for_elements(".radiostyle")
        sleep 3
        
        if page.has_content?"Content Rights"
          # Looks good.. just a few more steps

          perms ||= {
            export_compliance: {
              encryption_updated: false,
              cryptography_enabled: false,
              is_exempt: false
            },
            third_party_content: {
              contains_third_party_content: false,
              has_rights: false
            },
            advertising_identifier: {
              use_idfa: false,
              serve_advertisement: false,
              attribute_advertisement: false,
              attribute_actions: false,
              limit_ad_tracking: false
            }
          }

          basic = "//*[@itc-radio='submitForReviewAnswers"
          checkbox = "//*[@itc-checkbox='submitForReviewAnswers"

          #####################
          # Export Compliance #
          #####################
          if page.has_content?"Export"
            
            if not perms[:export_compliance][:encryption_updated] and perms[:export_compliance][:cryptography_enabled]
              raise "encryption_updated must be enabled if cryptography_enabled is enabled!"
            end

            begin
              encryption_updated_control = all(:xpath, "#{basic}.exportCompliance.encryptionUpdated.value' and @radio-value='#{perms[:export_compliance][:encryption_updated]}']//input")
              encryption_updated_control[0].trigger('click') if encryption_updated_control.count > 0
              first(:xpath, "#{basic}.exportCompliance.usesEncryption.value' and @radio-value='#{perms[:export_compliance][:cryptography_enabled]}']//input").trigger('click')
              first(:xpath, "#{basic}.exportCompliance.isExempt.value' and @radio-value='#{perms[:export_compliance][:is_exempt]}']//input").trigger('click')
            rescue
            end
          end

          ##################
          # Content Rights #
          ##################
          if page.has_content?"Content Rights"
            if not perms[:third_party_content][:contains_third_party_content] and perms[:third_party_content][:has_rights]
              raise "contains_third_party_content must be enabled if has_rights is enabled".red
            end

            begin
              first(:xpath, "#{basic}.contentRights.containsThirdPartyContent.value' and @radio-value='#{perms[:third_party_content][:contains_third_party_content]}']//input").trigger('click')
              first(:xpath, "#{basic}.contentRights.hasRights.value' and @radio-value='#{perms[:third_party_content][:has_rights]}']//input").trigger('click')
            rescue
            end
          end

          ##########################
          # Advertising Identifier #
          ##########################
          if page.has_content?"Advertising Identifier"
            first(:xpath, "#{basic}.adIdInfo.usesIdfa.value' and @radio-value='#{perms[:advertising_identifier][:use_idfa]}']//a").click rescue nil

            if perms[:advertising_identifier][:use_idfa]
              if perms[:advertising_identifier][:serve_advertisement]
                first(:xpath, "#{checkbox}.adIdInfo.servesAds.value']//a").click
              end
              if perms[:advertising_identifier][:attribute_advertisement]
                first(:xpath, "#{checkbox}.adIdInfo.tracksInstall.value']//a").click
              end
              if perms[:advertising_identifier][:attribute_actions]
                first(:xpath, "#{checkbox}.adIdInfo.tracksAction.value']//a").click
              end
              if perms[:advertising_identifier][:limit_ad_tracking]
                first(:xpath, "#{checkbox}.adIdInfo.limitsTracking.value']//a").click
              end
            end
          end
          

          Helper.log.info("Filled out the export compliance and other information on iTC".green)

          click_on "Submit"
          sleep 5

          if page.has_content?WAITING_FOR_REVIEW
            # Everything worked :)
            Helper.log.info("Successfully submitted App for Review".green)
            return true
          else
            raise "So close, it looks like there went something wrong with the actual deployment. Checkout '#{current_url}'".red
          end
        else
          raise "Something is missing here.".red
        end
        return false
      rescue => ex
        error_occured(ex)
      end
    end

  end
end