/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * 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
 *
 *      http://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 android.security.cts.CVE_2021_0481;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.SystemClock;
import android.util.Log;

import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import androidx.test.filters.SdkSuppress;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
import androidx.test.uiautomator.BySelector;

import java.util.List;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertFalse;
import static org.junit.Assume.assumeNoException;

/**
 * launch "Settings" app
 * set up user photo
 */
@RunWith(AndroidJUnit4.class)
public class DeviceTest {

  class ClickableNotFound extends Exception{
    public ClickableNotFound(String s){
      super(s);
    }
  }

  private static final String BASIC_SAMPLE_PACKAGE
          = "android.security.cts.CVE_2021_0481";
  private static final int LAUNCH_TIMEOUT_MS = 20000;
  private static final String TAG = "TAG_2021_0481";
  private static final int IS_FOUND_FLAG = 1;          // 0001
  private static final int IS_CHECKED_FLAG = 2;        // 0010
  private UiDevice mDevice;

  @Test
  public void testUserPhotoSetUp() {

    //set mDevice and go to homescreen
    mDevice = UiDevice.getInstance(getInstrumentation());
    mDevice.pressHome();

    //start "Settings" app
    Intent myIntent = new Intent("android.settings.USER_SETTINGS");
                                //android.provider.Settings.ACTION_USER_SETTINGS
    myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    try{
      getApplicationContext().startActivity(myIntent);
    } catch(android.content.ActivityNotFoundException e){
      Log.d(TAG, "Activity to be tested  doesn't exist. Test will pass.");
      return;
    }

    //wait for "User Settings" activity to appear.
    SystemClock.sleep(6000);

    //perform UI test steps
    try {

      //in "Multiple users" activity showing "Use multiple users" switch
      searchAndClick(mDevice, "android:id/switch_widget", 2000);

      //in "Multiple users" activity showing a list of current users,
      //look for the first item "android:id/title" on the list showing "You(Owner)"
      searchAndClick(mDevice, "android:id/title", 2000);

      //in "Profile Info" dialog window showing clickable user silhouette
      //look for clickable android.widget.ImageView object with attributes:
      // getContentDescription()=Select photo
      // getResourceName()=com.android.settings:id/user_photo
      searchAndClick(mDevice, "com.android.settings:id/user_photo", 2000);

      //in unnamed subdialog showing two options: "Take a photo" "Choose an image"
      searchAndClick(mDevice, "Choose an image", 6000);

      //in "Browse Files in Other Apps" activity
      searchAndClick(mDevice, "android.security.cts.CVE_2021_0481.EvilActivity", 5000);

      //Image is chosen as (evilActivity) so we are getting back to
      //"Profile Info" dialog window showing clickable user silhouette
      //end "Cancel" and "OK" buttons.
      //look for "Cancel button and click it"
      searchAndClick(mDevice, "Cancel", 2000);

    } catch (ClickableNotFound e){
      Log.d(TAG, e.toString());
      assumeNoException(e);
    }
    Log.d(TAG, "end of testUserPhotoSetUp()");
  }

  //see what is on screen and click on object containing name
  //throw exception if object not found
  private void searchAndClick(UiDevice mDevice, String name, int timeOut) throws ClickableNotFound {

    int ret;
    List<UiObject2> objects = mDevice.findObjects(By.clickable(true));
    boolean found = false;
    Log.d(TAG, "looking for " + name);
    Log.d(TAG, "found " + String.valueOf(objects!=null ? objects.size() : 0) + " clickables");

    if(objects != null){
      for (UiObject2 o : objects) {
        if((ret=searchAndLog(o, name, "")) !=0 )
        {
          found=true;
          Log.d(TAG, name + " found");
          if((ret & IS_CHECKED_FLAG) == 0) {
              o.click();
              Log.d(TAG, name + " clicked");
              SystemClock.sleep(timeOut); //wait for click result to appear onscreen
          }
          break; //to avoid androidx.test.uiautomator.StaleObjectException
        }
      }
    }
    if(!found) {
      throw new ClickableNotFound("\"" + name + "\" not found to click on");
    }
  }

  //Search for 'name' in UiObject2
  //returns int flags showing search result:
  // IS_CHECKED_FLAG - 'name' matches o.getResourceName() and o.isSelected()==true
  // IS_FOUND_FLAG - 'name' matches anything else
  private int searchAndLog(UiObject2 o, String name, String prefix){

    int ret = 0;
    String lname = o.getText();
    String cname = o.getClassName();
    String cdesc = o.getContentDescription();
    String rname = o.getResourceName();
    boolean checked = o.isChecked();

    Log.d(TAG, prefix + "class=" + cname);
    Log.d(TAG, prefix + "o.getText()=" + lname);
    Log.d(TAG, prefix + "o.getContentDescription()=" + cdesc);
    Log.d(TAG, prefix + "o.getResourceName()=" + rname);
    Log.d(TAG, prefix + "o.getChildCount()=" + o.getChildCount());

    if( rname != null && rname.equals(name) && checked) {
      ret |= IS_CHECKED_FLAG;
    }
    else if(lname != null && lname.equals(name) || cdesc != null && cdesc.equals(name) || rname != null && rname.equals(name) ) {
      ret |= IS_FOUND_FLAG;
    }

    if(ret != 0) {
      Log.d(TAG, prefix + "found-->" + name);
      return ret;
    } else {
      java.util.List<UiObject2> objects2 = o.getChildren();
      if(objects2 != null && objects2.size() > 0 && prefix.length() < 50) {
        for (UiObject2 o2 : objects2) {
          if((ret=searchAndLog(o2, name, prefix + "__")) != 0){
            return ret;
          }
        }
      }
    }
    return ret;
  }

}

