// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.google.dart.compiler;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.JarURLConnection;
import java.net.URI;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.jar.JarEntry;

/**
 * A {@link Source} backed by a URL (or optionally by a file).
 */
public abstract class UrlSource implements Source {

  private final static String FILE_PROTOCOL = "file";
  private final static String JAR_PROTOCOL = "jar";
  private final static URI CURRENT_DIR = new File(".").toURI().normalize();
  private final static Charset UTF8 = Charset.forName("UTF8");
  private final static URI BASE_URI = CURRENT_DIR;

  private final URI uri;
  private final URI absoluteUri;
  private final URI translatedUri;
  private final boolean shouldCareAboutLastModified;
  private volatile boolean exists = false;
  private volatile long lastModified = -1;
  private volatile boolean propertiesInitialized = false;

  // generally, one or the other of these will be non-null after properties are initialized
  private volatile File sourceFile = null;
  private volatile JarURLConnection jarConn = null;

  protected final PackageLibraryManager packageLibraryManager;

  protected UrlSource(URI uri) {
    this(uri,null);
  }

  protected UrlSource(URI uri, PackageLibraryManager slm) {
    URI expanded = slm != null ? slm.expandRelativeDartUri(uri) : uri;
    if (expanded == null) {
      // import("dart:typo") case
      expanded = uri;
    }
    this.uri = BASE_URI.relativize(expanded.normalize());
    this.absoluteUri = BASE_URI.resolve(expanded);
    this.packageLibraryManager = slm;
    if (PackageLibraryManager.isDartUri(this.uri) || PackageLibraryManager.isPackageUri(this.uri)) {
      assert slm != null;
      this.shouldCareAboutLastModified = false;
      this.translatedUri = slm.resolveDartUri(this.absoluteUri);
    } else {
      this.shouldCareAboutLastModified = true;
      this.translatedUri = this.absoluteUri;
    }
  }

  protected UrlSource(File file) {
    URI uri = file.toURI().normalize();
    if (!file.exists()) {
      // TODO(jgw): This is a bit ugly, but some of the test infrastructure depends upon
      // non-existant relative files being looked up as classpath resources. This was
      // previously embedded in DartSourceFile.getSourceReader().
      URL url = getClass().getClassLoader().getResource(file.getPath());
      if (url != null) {
        uri = URI.create(url.toString());
      }
    }

    this.uri = BASE_URI.relativize(uri);
    this.translatedUri = this.absoluteUri = BASE_URI.resolve(uri);
    this.packageLibraryManager = null;
    this.shouldCareAboutLastModified = true;
  }

  @Override
  public boolean exists() {
    initProperties();
    return exists;
  }

  @Override
  public long getLastModified() {
    initProperties();
    return lastModified;
  }

  @Override
  public Reader getSourceReader() throws IOException {
    initProperties();
    if (sourceFile != null) {
      return new InputStreamReader(new FileInputStream(sourceFile), UTF8);
    } else if (jarConn != null) {
      return new InputStreamReader(jarConn.getInputStream(), UTF8);
    }
    // fall back case
    if (translatedUri != null) {
      InputStream stream = translatedUri.toURL().openStream();
      if (stream != null) {
        return new InputStreamReader(stream, UTF8);
      }
    }
    throw new FileNotFoundException(getName());
  }

  @Override
  public String getUniqueIdentifier() {
    return absoluteUri.toString();
  }

  /**
   * Get the translated URI for this source.
   * 
   * @return the translated URI
   */
  public URI getTranslatedUri() {
    return translatedUri;
  }
  
  @Override
  public URI getUri() {
    return absoluteUri;
  }

  private void initProperties() {
    synchronized (this) {
      if (!propertiesInitialized) {
        try {
          initPropertiesEx();
        } catch (Throwable e) {
        } finally {
          propertiesInitialized = true;
        }
      }
    }
  }

  /**
   * Implementation of {@link #initProperties()} which can throw exceptions.
   */
  private void initPropertiesEx() throws Exception {
    URI resolvedUri = BASE_URI.resolve(translatedUri);
    String scheme = resolvedUri.getScheme();
    if (scheme == null || FILE_PROTOCOL.equals(scheme)) {
      File file = new File(resolvedUri);
      lastModified = file.lastModified();
      exists = file.exists();
      sourceFile = file;
    } else {
      URL url = translatedUri.toURL();
      if (JAR_PROTOCOL.equals(url.getProtocol())) {
        getJarEntryProperties(url);
      } else {
        /*
         * TODO(jbrosenberg): Flesh out the support for other
         * protocols, like http, etc. Note, calling
         * URLConnection.getLastModified() can be dangerous, some
         * URLConnection sub-classes don't have a way to close a
         * connection opened by this call. Return 0 for now.
         */
        lastModified = 0;
        // Default this to true for now.
        exists = true;
      }
    }
  }

  private void getJarEntryProperties(URL url) {
    try {
      jarConn = (JarURLConnection) url.openConnection();
      // useCaches is usually set to true by default, but make sure here
      jarConn.setUseCaches(true);
      // See if our entry exists
      JarEntry jarEntry = jarConn.getJarEntry();
      if (jarEntry != null) {
        exists = true;
        if (!shouldCareAboutLastModified) {
          lastModified = 0;
          return;
        }
        // TODO(jbrosenberg): Note the time field for a jarEntry can be
        // unreliable, and is not always required in a jar file. Consider using
        // the timestamp on the jar file itself.
        lastModified = jarEntry.getTime();
      }
      if (!exists) {
        lastModified = -1;
        return;
      }
    } catch (IOException e) {
      exists = false;
      lastModified = -1;
    }
  }
}