/*
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.firebase.messaging.testing.fcmexternalprobertarget;

import android.content.Context;
import android.content.Intent;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

import java.time.Clock;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

/**
 * Service that handles interaction with Firebase Cloud Messaging, and logs the results of the
 * messages both to the UI and files.
 */
public class FCMReceiveService extends FirebaseMessagingService {

    private Context context;
    private boolean viewLogging;
    private Clock logTimer;

    public FCMReceiveService () {
        this.context = this;
        viewLogging = false;
        logTimer = Clock.systemUTC();
    }

    /**
     * Create an instance for testing
     * @param context Mocked Context object
     * @param viewLogging Whether logs should be written to UI
     */
    @VisibleForTesting
    public FCMReceiveService (Context context, boolean viewLogging, Clock logTimer) {
        this.context = context;
        this.viewLogging = viewLogging;
        this.logTimer = logTimer;
    }

    @Override
    public void onNewToken(@NonNull String token) {
        // Store token in a file on external storage so it can be accessed by the probe
        File tokenFile = makeExternalFile("","token.txt");
        writeToFile(tokenFile, token);
        logToUI("Info", "Token generated");
    }

    @Override
    public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
        long receivedTime = logTimer.instant().getEpochSecond();
        String sendTime = remoteMessage.getData().get("sendTime");
        File logFile = makeExternalFile("logs", sendTime + ".txt");
        writeToFile(logFile, Long.toString(receivedTime));
        logToUI("Info","Message Received: " + sendTime + ".txt");
    }


    private void logToUI(String tag, String logText) {
        Log.d(tag, logText);
        if (viewLogging) {
            return;
        }
        Intent intent = new Intent("updateUI");
        intent.putExtra("logText", tag + ": " + logText);
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }

    private File makeExternalFile(String path, String fileName) {
        File newPath = new File(context.getExternalFilesDir(null), path);
        if (!newPath.exists()) {
            if (!newPath.mkdirs()) {
                logToUI("Error", "Unable to create directory " + path);
            }
            else {
                logToUI("Info", "Directory " + path + " created");
            }
        }
        return new File(newPath, fileName);
    }

    private void writeToFile(File writeFile, String writeText) {
        try {
            FileWriter outputWriter = new FileWriter(writeFile);
            outputWriter.write(writeText, 0, writeText.length());
            outputWriter.close();
        } catch (IOException exception) {
            logToUI("Error", exception.toString());
        }
    }
}

@@ -2092,16 +2092,34 @@
 e probe%0A
+        try %7B%0A    
         
@@ -2155,16 +2155,17 @@
 File(%22%22,
+ 
 %22token.t
@@ -2170,32 +2170,36 @@
 .txt%22);%0A        
+    
 writeToFile(toke
@@ -2213,16 +2213,120 @@
 token);%0A
+        %7D catch (IOException exception) %7B%0A            logToUI(%22Error%22, exception.toString());%0A        %7D%0A
         
@@ -2353,24 +2353,48 @@
 en generated
+ and stored in token.txt
 %22);%0A    %7D%0A%0A 
@@ -2608,24 +2608,42 @@
 sendTime%22);%0A
+        try %7B%0A    
         File
@@ -2698,32 +2698,36 @@
 .txt%22);%0A        
+ 
+   
 writeToFile(logF
@@ -2757,24 +2757,128 @@
 ivedTime));%0A
+        %7D catch (IOException exception) %7B%0A            logToUI(%22Error%22, exception.toString());%0A        %7D%0A
         logT
@@ -2901,18 +2901,37 @@
 age 
-R
+r
 eceived
-:
  
+and stored in: logs/
 %22 + 
@@ -3347,16 +3347,34 @@
 leName) 
+throws IOException
 %7B%0A      
@@ -3531,61 +3531,68 @@
     
-logToUI(%22Error%22, %22Unable to create directory %22 + path
+throw new IOException(%22Could not create specified directory%22
 );%0A 
@@ -3832,28 +3832,28 @@
 xt) 
-%7B%0A        try %7B%0A    
+throws IOException%7B%0A
     
@@ -3909,36 +3909,32 @@
 eFile);%0A        
-    
 outputWriter.wri
@@ -3975,28 +3975,24 @@
 ));%0A        
-  
-  
 outputWriter
@@ -4005,112 +4005,8 @@
 ();%0A
-        %7D catch (IOException exception) %7B%0A            logToUI(%22Error%22, exception.toString());%0A        %7D%0A
     

modify error handling in file IO functions