// Copyright (C) 2009 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 com.google.gwtexpui.css.rebind;

import com.google.gwt.core.ext.LinkerContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.AbstractLinker;
import com.google.gwt.core.ext.linker.Artifact;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.core.ext.linker.LinkerOrder;
import com.google.gwt.core.ext.linker.PublicResource;
import com.google.gwt.core.ext.linker.impl.StandardLinkerContext;
import com.google.gwt.core.ext.linker.impl.StandardStylesheetReference;
import com.google.gwt.dev.util.Util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

@LinkerOrder(LinkerOrder.Order.PRE)
public class CssLinker extends AbstractLinker {
  @Override
  public String getDescription() {
    return "CssLinker";
  }

  @Override
  public ArtifactSet link(
      final TreeLogger logger, final LinkerContext context, final ArtifactSet artifacts)
      throws UnableToCompleteException {
    final ArtifactSet returnTo = new ArtifactSet();
    int index = 0;

    final HashMap<String, PublicResource> css = new HashMap<>();

    for (final StandardStylesheetReference ssr :
        artifacts.<StandardStylesheetReference>find(StandardStylesheetReference.class)) {
      css.put(ssr.getSrc(), null);
    }
    for (final PublicResource pr : artifacts.<PublicResource>find(PublicResource.class)) {
      if (css.containsKey(pr.getPartialPath())) {
        css.put(pr.getPartialPath(), new CssPubRsrc(name(logger, pr), pr));
      }
    }

    for (Artifact<?> a : artifacts) {
      if (a instanceof PublicResource) {
        final PublicResource r = (PublicResource) a;
        if (css.containsKey(r.getPartialPath())) {
          a = css.get(r.getPartialPath());
        }
      } else if (a instanceof StandardStylesheetReference) {
        final StandardStylesheetReference r = (StandardStylesheetReference) a;
        final PublicResource p = css.get(r.getSrc());
        a = new StandardStylesheetReference(p.getPartialPath(), index);
      }

      returnTo.add(a);
      index++;
    }
    return returnTo;
  }

  private String name(final TreeLogger logger, final PublicResource r)
      throws UnableToCompleteException {
    byte[] out;
    try (ByteArrayOutputStream tmp = new ByteArrayOutputStream();
        InputStream in = r.getContents(logger)) {
      final byte[] buf = new byte[2048];
      int n;
      while ((n = in.read(buf)) >= 0) {
        tmp.write(buf, 0, n);
      }
      out = tmp.toByteArray();
    } catch (IOException e) {
      final UnableToCompleteException ute = new UnableToCompleteException();
      ute.initCause(e);
      throw ute;
    }

    String base = r.getPartialPath();
    final int s = base.lastIndexOf('/');
    if (0 < s) {
      base = base.substring(0, s + 1);
    } else {
      base = "";
    }
    return base + Util.computeStrongName(out) + ".cache.css";
  }

  private static class CssPubRsrc extends PublicResource {
    private static final long serialVersionUID = 1L;
    private final PublicResource src;

    CssPubRsrc(final String partialPath, final PublicResource r) {
      super(StandardLinkerContext.class, partialPath);
      src = r;
    }

    @Override
    public InputStream getContents(final TreeLogger logger) throws UnableToCompleteException {
      return src.getContents(logger);
    }

    @Override
    public long getLastModified() {
      return src.getLastModified();
    }
  }
}
