/*
 * 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.MorePaths;
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 MorePaths.newPathInstance(
        new File(dir, String.format("drawable-%s/%s", qualifier, filename))).toString();
  }

  @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);
  }
}
