/*
 * Copyright 2012-present Facebook, Inc.
 *
 * 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 com.facebook.buck.android;

import static org.junit.Assert.assertEquals;

import com.facebook.buck.android.FilterResourcesStep.ImageScaler;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.util.FilteredDirectoryCopier;
import com.facebook.buck.util.Filters;
import com.facebook.buck.util.Paths;
import com.facebook.buck.util.ProcessExecutor;
import com.facebook.buck.util.ProjectFilesystem;
import com.facebook.buck.util.Verbosity;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

import org.easymock.Capture;
import org.easymock.EasyMock;
import org.easymock.IAnswer;
import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class FilterResourcesStepTest {

  private final static String first = "/first-path/res";
  private final static String second = "/second-path/res";
  private final static String third = "/third-path/res";

  private final static ImmutableSet<String> resDirectories = ImmutableSet.of(first, second, third);
  private static Set<String> qualifiers = ImmutableSet.of("mdpi", "hdpi", "xhdpi");
  private final String targetDensity = "mdpi";
  private final File baseDestination = new File("/dest");

  private final String scaleSource = getFile(first, "xhdpi", "other.png");
  private final String scaleDest = getFile(first, "mdpi", "other.png");

  private String getFile(String dir, String qualifier, String filename) {
    return Paths.normalizePathSeparator(
        new File(dir, String.format("drawable-%s/%s", qualifier, filename)).getPath());
  }

  @Test
  public void testFilterResourcesCommand() throws IOException {

    // Mock a ProjectFilesystem. This will be called into by the image downscaling step.
    ProjectFilesystem filesystem = EasyMock.createMock(ProjectFilesystem.class);
    EasyMock
      .expect(filesystem.getFileForRelativePath(EasyMock.<String>anyObject()))
      .andAnswer(new IAnswer<File>(){
          @Override
          public File answer() throws Throwable {
             return new File(String.valueOf(EasyMock.getCurrentArguments()[0]));
          }})
      .anyTimes();
    filesystem.createParentDirs(scaleDest);
    EasyMock.expect(filesystem.deleteFileAtPath(scaleSource)).andReturn(true);
    String scaleSourceDir = new File(scaleSource).getParent();
    EasyMock.expect(filesystem.listFiles(scaleSourceDir)).andReturn(new File[0]);
    EasyMock.expect(filesystem.deleteFileAtPath(scaleSourceDir)).andReturn(true);
    EasyMock.replay(filesystem);

    // Mock an ExecutionContext.
    ExecutionContext context = EasyMock.createMock(ExecutionContext.class);
    ProcessExecutor processExecutor = EasyMock.createMock(ProcessExecutor.class);
    EasyMock.expect(context.getProcessExecutor()).andReturn(processExecutor).anyTimes();
    EasyMock.expect(context.getVerbosity()).andReturn(Verbosity.SILENT).anyTimes();
    EasyMock.expect(context.getProjectFilesystem()).andReturn(filesystem).anyTimes();
    EasyMock.replay(context);

    // Create a mock DrawableFinder, just creates one drawable/density/resource dir.
    FilterResourcesStep.DrawableFinder finder = EasyMock.createMock(
        FilterResourcesStep.DrawableFinder.class);

    // Create mock FilteredDirectoryCopier to find what we're calling on it.
    FilteredDirectoryCopier copier = EasyMock.createMock(FilteredDirectoryCopier.class);
    // We'll want to see what the filtering command passes to the copier.
    Capture<Map<String, String>> dirMapCapture = new Capture<Map<String, String>>();
    Capture<Predicate<File>> predCapture = new Capture<Predicate<File>>();
    copier.copyDirs(EasyMock.capture(dirMapCapture),
        EasyMock.capture(predCapture));
    EasyMock.replay(copier);

    ImageScaler scaler = EasyMock.createMock(FilterResourcesStep.ImageScaler.class);
    scaler.scale(
        0.5,
        scaleSource,
        scaleDest,
        context
    );

    EasyMock.expect(scaler.isAvailable(context)).andReturn(true);
    EasyMock.replay(scaler);

    FilterResourcesStep command = new FilterResourcesStep(
        resDirectories,
        baseDestination,
        targetDensity,
        copier,
        finder,
        scaler);

    EasyMock
      .expect(finder.findDrawables(resDirectories))
      .andAnswer(new IAnswer<Set<String>>() {
        @SuppressWarnings("unchecked")
        @Override
        public Set<String> answer() throws Throwable {
          ImmutableSet.Builder<String> builder = ImmutableSet.builder();
          for (String dir : (Iterable<String>) EasyMock.getCurrentArguments()[0]) {
            for (String qualifier : qualifiers) {
              builder.add(getFile(dir, qualifier, "some.png"));
            }
          }

          builder.add(scaleSource);

          return builder.build();
        }
      })
      .times(2); // We're calling it in the test as well.

    // Called by the downscaling step.
    EasyMock
      .expect(finder.findDrawables(command.getFilteredResourceDirectories()))
      .andAnswer(new IAnswer<Set<String>>() {
        @SuppressWarnings("unchecked")
        @Override
        public Set<String> answer() throws Throwable {
          ImmutableSet.Builder<String> builder = ImmutableSet.builder();
          for (String dir : (Iterable<String>) EasyMock.getCurrentArguments()[0]) {
            builder.add(getFile(dir, targetDensity, "some.png"));
          }

          builder.add(scaleSource);
          return builder.build();
        }
      })
      .once();
    EasyMock.replay(finder);

    // We'll use this to verify the source->destination mappings created by the command.
    ImmutableMap.Builder<String, String> dirMapBuilder = ImmutableMap.builder();

    Iterator<String> destIterator = command.getFilteredResourceDirectories().iterator();
    for(String dir : resDirectories) {
      String nextDestination = destIterator.next();
      dirMapBuilder.put(dir, nextDestination);

      // Verify that destination path requirements are observed.
      assertEquals(baseDestination, new File(nextDestination).getParentFile());
    }

    // Execute command.
    command.execute(context);

    // Ensure resources are copied to the right places.
    assertEquals(dirMapBuilder.build(), dirMapCapture.getValue());

    // Ensure the right filter is created.
    Set<String> drawables = finder.findDrawables(resDirectories);
    Predicate<File> expectedPred = Filters.createImageDensityFilter(drawables, targetDensity);
    Predicate<File> capturedPred = predCapture.getValue();
    for (String drawablePath : drawables) {
      File drawableFile = new File(drawablePath);
      assertEquals(expectedPred.apply(drawableFile), capturedPred.apply(drawableFile));
    }

    // We shouldn't need the execution context, should call copyDirs once on the copier,
    // and we're calling finder.findDrawables twice.
    EasyMock.verify(copier, context, finder, filesystem, scaler);
  }
}
