/*
 * Copyright 2009 Google 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.google.gwt.user.linker.rpc;

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.ArtifactSet;
import com.google.gwt.core.ext.linker.EmittedArtifact;
import com.google.gwt.core.ext.linker.LinkerOrder;
import com.google.gwt.core.ext.linker.Shardable;
import com.google.gwt.core.ext.linker.SyntheticArtifact;
import com.google.gwt.core.ext.linker.LinkerOrder.Order;
import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.util.Util;
import com.google.gwt.user.rebind.rpc.ProxyCreator;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

/**
 * Emit a file containing a map of RPC proxy classes to the partial path of the
 * RPC policy file.
 */
@LinkerOrder(Order.PRE)
@Shardable
public class RpcPolicyManifestLinker extends AbstractLinker {
  private static final String MANIFEST_TXT = "manifest.txt";

  /**
   * The main body of the manifest. It is built up as per-permutation manifests
   * are looped over.
   */
  private StringBuilder manifestBody = new StringBuilder();

  @Override
  public String getDescription() {
    return "RPC policy file manifest";
  }

  @Override
  public ArtifactSet link(TreeLogger logger, LinkerContext context,
      ArtifactSet artifacts, boolean onePermutation)
      throws UnableToCompleteException {
    if (onePermutation) {
      return artifacts;
    } else {
      for (EmittedArtifact art : artifacts.find(EmittedArtifact.class)) {
        if (art.getPartialPath().startsWith(ProxyCreator.MANIFEST_ARTIFACT_DIR)) {
          readOneManifest(logger, art.getContents(logger));
        }
      }

      ArtifactSet toReturn = new ArtifactSet(artifacts);
      SyntheticArtifact manifestArt = emitString(logger,
          generateManifest(context), MANIFEST_TXT);
      manifestArt.setPrivate(true);
      toReturn.add(manifestArt);
      return toReturn;
    }
  }

  /**
   * Compute a manifest for all RPC policy files seen so far.
   */
  private String generateManifest(LinkerContext context) {
    StringBuilder sb = new StringBuilder();
    sb.append("# Module " + context.getModuleName() + "\n");
    sb.append("# RPC service class, partial path of RPC policy file\n");
    sb.append(manifestBody.toString());
    return sb.toString();
  }

  /**
   * Read one manifest and close the input stream.
   */
  private void readOneManifest(TreeLogger logger, InputStream manifestStream)
      throws UnableToCompleteException {
    Map<String, String> entries = new HashMap<String, String>();
    try {
      BufferedReader reader = new BufferedReader(new InputStreamReader(
          manifestStream, Util.DEFAULT_ENCODING));
      String line;
      while ((line = reader.readLine()) != null) {
        int idx = line.indexOf(':');
        if (idx < 0) {
          throw new InternalCompilerException(
              "invalid selection information line: " + line);
        }
        String propName = line.substring(0, idx).trim();
        String propValue = line.substring(idx + 1).trim();
        entries.put(propName, propValue);
      }
      reader.close();
    } catch (IOException e) {
      logger.log(TreeLogger.ERROR, "Unexpected IOException", e);
      throw new UnableToCompleteException();
    }

    String serviceClass = entries.get("serviceClass");
    if (serviceClass == null) {
      logger.log(TreeLogger.ERROR,
          "Internal error: manifest file does not include a serviceClass");
      throw new UnableToCompleteException();
    }
    String path = entries.get("path");
    if (path == null) {
      logger.log(TreeLogger.ERROR,
          "Internal error: manifest file does not include a path");
      throw new UnableToCompleteException();
    }

    manifestBody.append(serviceClass);
    manifestBody.append(", ");
    manifestBody.append(path);
    manifestBody.append("\n");
  }
}
