/*
 * Copyright (C) 2018 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.view.textclassifier;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Mockito.when;

import android.os.LocaleList;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.function.Supplier;
import java.util.stream.Collectors;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class ModelFileManagerTest {
    private static final Locale DEFAULT_LOCALE = Locale.forLanguageTag("en-US");
    @Mock
    private Supplier<List<ModelFileManager.ModelFile>> mModelFileSupplier;
    private ModelFileManager.ModelFileSupplierImpl mModelFileSupplierImpl;
    private ModelFileManager mModelFileManager;
    private File mRootTestDir;
    private File mFactoryModelDir;
    private File mUpdatedModelFile;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        mModelFileManager = new ModelFileManager(mModelFileSupplier);
        mRootTestDir = InstrumentationRegistry.getContext().getCacheDir();
        mFactoryModelDir = new File(mRootTestDir, "factory");
        mUpdatedModelFile = new File(mRootTestDir, "updated.model");

        mModelFileSupplierImpl =
                new ModelFileManager.ModelFileSupplierImpl(
                        mFactoryModelDir,
                        "test\\d.model",
                        mUpdatedModelFile,
                        fd -> 1,
                        fd -> ModelFileManager.ModelFile.LANGUAGE_INDEPENDENT
                );

        mRootTestDir.mkdirs();
        mFactoryModelDir.mkdirs();

        Locale.setDefault(DEFAULT_LOCALE);
    }

    @After
    public void removeTestDir() {
        recursiveDelete(mRootTestDir);
    }

    @Test
    public void get() {
        ModelFileManager.ModelFile modelFile =
                new ModelFileManager.ModelFile(
                        new File("/path/a"), 1, Collections.emptyList(), "", true);
        when(mModelFileSupplier.get()).thenReturn(Collections.singletonList(modelFile));

        List<ModelFileManager.ModelFile> modelFiles = mModelFileManager.listModelFiles();

        assertThat(modelFiles).hasSize(1);
        assertThat(modelFiles.get(0)).isEqualTo(modelFile);
    }

    @Test
    public void findBestModel_versionCode() {
        ModelFileManager.ModelFile olderModelFile =
                new ModelFileManager.ModelFile(
                        new File("/path/a"), 1,
                        Collections.emptyList(), "", true);

        ModelFileManager.ModelFile newerModelFile =
                new ModelFileManager.ModelFile(
                        new File("/path/b"), 2,
                        Collections.emptyList(), "", true);
        when(mModelFileSupplier.get())
                .thenReturn(Arrays.asList(olderModelFile, newerModelFile));

        ModelFileManager.ModelFile bestModelFile =
                mModelFileManager.findBestModelFile(LocaleList.getEmptyLocaleList());

        assertThat(bestModelFile).isEqualTo(newerModelFile);
    }

    @Test
    public void findBestModel_languageDependentModelIsPreferred() {
        Locale locale = Locale.forLanguageTag("ja");
        ModelFileManager.ModelFile languageIndependentModelFile =
                new ModelFileManager.ModelFile(
                        new File("/path/a"), 1,
                        Collections.emptyList(), "", true);

        ModelFileManager.ModelFile languageDependentModelFile =
                new ModelFileManager.ModelFile(
                        new File("/path/b"), 1,
                        Collections.singletonList(locale), locale.toLanguageTag(), false);
        when(mModelFileSupplier.get())
                .thenReturn(
                        Arrays.asList(languageIndependentModelFile, languageDependentModelFile));

        ModelFileManager.ModelFile bestModelFile =
                mModelFileManager.findBestModelFile(
                        LocaleList.forLanguageTags(locale.toLanguageTag()));
        assertThat(bestModelFile).isEqualTo(languageDependentModelFile);
    }

    @Test
    public void findBestModel_noMatchedLanguageModel() {
        Locale locale = Locale.forLanguageTag("ja");
        ModelFileManager.ModelFile languageIndependentModelFile =
                new ModelFileManager.ModelFile(
                        new File("/path/a"), 1,
                        Collections.emptyList(), "", true);

        ModelFileManager.ModelFile languageDependentModelFile =
                new ModelFileManager.ModelFile(
                        new File("/path/b"), 1,
                        Collections.singletonList(locale), locale.toLanguageTag(), false);

        when(mModelFileSupplier.get())
                .thenReturn(
                        Arrays.asList(languageIndependentModelFile, languageDependentModelFile));

        ModelFileManager.ModelFile bestModelFile =
                mModelFileManager.findBestModelFile(
                        LocaleList.forLanguageTags("zh-hk"));
        assertThat(bestModelFile).isEqualTo(languageIndependentModelFile);
    }

    @Test
    public void findBestModel_noMatchedLanguageModel_defaultLocaleModelExists() {
        ModelFileManager.ModelFile languageIndependentModelFile =
                new ModelFileManager.ModelFile(
                        new File("/path/a"), 1,
                        Collections.emptyList(), "", true);

        ModelFileManager.ModelFile languageDependentModelFile =
                new ModelFileManager.ModelFile(
                        new File("/path/b"), 1,
                        Collections.singletonList(
                                DEFAULT_LOCALE), DEFAULT_LOCALE.toLanguageTag(), false);

        when(mModelFileSupplier.get())
                .thenReturn(
                        Arrays.asList(languageIndependentModelFile, languageDependentModelFile));

        ModelFileManager.ModelFile bestModelFile =
                mModelFileManager.findBestModelFile(
                        LocaleList.forLanguageTags("zh-hk"));
        assertThat(bestModelFile).isEqualTo(languageIndependentModelFile);
    }

    @Test
    public void findBestModel_languageIsMoreImportantThanVersion() {
        ModelFileManager.ModelFile matchButOlderModel =
                new ModelFileManager.ModelFile(
                        new File("/path/a"), 1,
                        Collections.singletonList(Locale.forLanguageTag("fr")), "fr", false);

        ModelFileManager.ModelFile mismatchButNewerModel =
                new ModelFileManager.ModelFile(
                        new File("/path/b"), 2,
                        Collections.singletonList(Locale.forLanguageTag("ja")), "ja", false);

        when(mModelFileSupplier.get())
                .thenReturn(
                        Arrays.asList(matchButOlderModel, mismatchButNewerModel));

        ModelFileManager.ModelFile bestModelFile =
                mModelFileManager.findBestModelFile(
                        LocaleList.forLanguageTags("fr"));
        assertThat(bestModelFile).isEqualTo(matchButOlderModel);
    }

    @Test
    public void findBestModel_languageIsMoreImportantThanVersion_bestModelComesFirst() {
        ModelFileManager.ModelFile matchLocaleModel =
                new ModelFileManager.ModelFile(
                        new File("/path/b"), 1,
                        Collections.singletonList(Locale.forLanguageTag("ja")), "ja", false);

        ModelFileManager.ModelFile languageIndependentModel =
                new ModelFileManager.ModelFile(
                        new File("/path/a"), 2,
                        Collections.emptyList(), "", true);
        when(mModelFileSupplier.get())
                .thenReturn(
                        Arrays.asList(matchLocaleModel, languageIndependentModel));

        ModelFileManager.ModelFile bestModelFile =
                mModelFileManager.findBestModelFile(
                        LocaleList.forLanguageTags("ja"));

        assertThat(bestModelFile).isEqualTo(matchLocaleModel);
    }

    @Test
    public void modelFileEquals() {
        ModelFileManager.ModelFile modelA =
                new ModelFileManager.ModelFile(
                        new File("/path/a"), 1,
                        Collections.singletonList(Locale.forLanguageTag("ja")), "ja", false);

        ModelFileManager.ModelFile modelB =
                new ModelFileManager.ModelFile(
                        new File("/path/a"), 1,
                        Collections.singletonList(Locale.forLanguageTag("ja")), "ja", false);

        assertThat(modelA).isEqualTo(modelB);
    }

    @Test
    public void modelFile_different() {
        ModelFileManager.ModelFile modelA =
                new ModelFileManager.ModelFile(
                        new File("/path/a"), 1,
                        Collections.singletonList(Locale.forLanguageTag("ja")), "ja", false);

        ModelFileManager.ModelFile modelB =
                new ModelFileManager.ModelFile(
                        new File("/path/b"), 1,
                        Collections.singletonList(Locale.forLanguageTag("ja")), "ja", false);

        assertThat(modelA).isNotEqualTo(modelB);
    }


    @Test
    public void modelFile_getPath() {
        ModelFileManager.ModelFile modelA =
                new ModelFileManager.ModelFile(
                        new File("/path/a"), 1,
                        Collections.singletonList(Locale.forLanguageTag("ja")), "ja", false);

        assertThat(modelA.getPath()).isEqualTo("/path/a");
    }

    @Test
    public void modelFile_getName() {
        ModelFileManager.ModelFile modelA =
                new ModelFileManager.ModelFile(
                        new File("/path/a"), 1,
                        Collections.singletonList(Locale.forLanguageTag("ja")), "ja", false);

        assertThat(modelA.getName()).isEqualTo("a");
    }

    @Test
    public void modelFile_isPreferredTo_languageDependentIsBetter() {
        ModelFileManager.ModelFile modelA =
                new ModelFileManager.ModelFile(
                        new File("/path/a"), 1,
                        Collections.singletonList(Locale.forLanguageTag("ja")), "ja", false);

        ModelFileManager.ModelFile modelB =
                new ModelFileManager.ModelFile(
                        new File("/path/b"), 2,
                        Collections.emptyList(), "", true);

        assertThat(modelA.isPreferredTo(modelB)).isTrue();
    }

    @Test
    public void modelFile_isPreferredTo_version() {
        ModelFileManager.ModelFile modelA =
                new ModelFileManager.ModelFile(
                        new File("/path/a"), 2,
                        Collections.singletonList(Locale.forLanguageTag("ja")), "ja", false);

        ModelFileManager.ModelFile modelB =
                new ModelFileManager.ModelFile(
                        new File("/path/b"), 1,
                        Collections.emptyList(), "", false);

        assertThat(modelA.isPreferredTo(modelB)).isTrue();
    }

    @Test
    public void testFileSupplierImpl_updatedFileOnly() throws IOException {
        mUpdatedModelFile.createNewFile();
        File model1 = new File(mFactoryModelDir, "test1.model");
        model1.createNewFile();
        File model2 = new File(mFactoryModelDir, "test2.model");
        model2.createNewFile();
        new File(mFactoryModelDir, "not_match_regex.model").createNewFile();

        List<ModelFileManager.ModelFile> modelFiles = mModelFileSupplierImpl.get();
        List<String> modelFilePaths =
                modelFiles
                        .stream()
                        .map(modelFile -> modelFile.getPath())
                        .collect(Collectors.toList());

        assertThat(modelFiles).hasSize(3);
        assertThat(modelFilePaths).containsExactly(
                mUpdatedModelFile.getAbsolutePath(),
                model1.getAbsolutePath(),
                model2.getAbsolutePath());
    }

    @Test
    public void testFileSupplierImpl_empty() {
        mFactoryModelDir.delete();
        List<ModelFileManager.ModelFile> modelFiles = mModelFileSupplierImpl.get();

        assertThat(modelFiles).hasSize(0);
    }

    private static void recursiveDelete(File f) {
        if (f.isDirectory()) {
            for (File innerFile : f.listFiles()) {
                recursiveDelete(innerFile);
            }
        }
        f.delete();
    }
}
