/*
 * Copyright 2000-2009 JetBrains s.r.o.
 *
 * 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.intellij.openapi.vfs.impl.http;

import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.util.AsyncResult;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsBundle;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Url;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author nik
 */
public class RemoteFileInfoImpl implements RemoteContentProvider.DownloadingCallback, RemoteFileInfo {
  private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.http.RemoteFileInfoImpl");
  private final Object myLock = new Object();
  private final Url myUrl;
  private final RemoteFileManagerImpl myManager;
  private @Nullable RemoteContentProvider myContentProvider;
  private File myLocalFile;
  private VirtualFile myLocalVirtualFile;
  private VirtualFile myPrevLocalFile;
  private RemoteFileState myState = RemoteFileState.DOWNLOADING_NOT_STARTED;
  private String myErrorMessage;
  private final AtomicBoolean myCancelled = new AtomicBoolean();
  private final List<FileDownloadingListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();

  public RemoteFileInfoImpl(final @NotNull Url url, final @NotNull RemoteFileManagerImpl manager) {
    myUrl = url;
    myManager = manager;
  }

  @Override
  public void addDownloadingListener(@NotNull FileDownloadingListener listener) {
    myListeners.add(listener);
  }

  @Override
  public void removeDownloadingListener(final @NotNull FileDownloadingListener listener) {
    myListeners.remove(listener);
  }

  @Override
  public void restartDownloading() {
    synchronized (myLock) {
      myErrorMessage = null;
      myPrevLocalFile = myLocalVirtualFile;
      myLocalVirtualFile = null;
      myState = RemoteFileState.DOWNLOADING_NOT_STARTED;
      myLocalFile = null;
      startDownloading();
    }
  }

  @Override
  public void startDownloading() {
    LOG.debug("Downloading requested");

    File localFile;
    synchronized (myLock) {
      if (myState != RemoteFileState.DOWNLOADING_NOT_STARTED) {
        LOG.debug("File already downloaded: file = " + myLocalVirtualFile + ", state = " + myState);
        return;
      }
      myState = RemoteFileState.DOWNLOADING_IN_PROGRESS;

      try {
        myLocalFile = myManager.getStorage().createLocalFile(myUrl);
        LOG.debug("Local file created: " + myLocalFile.getAbsolutePath());
      }
      catch (IOException e) {
        LOG.info(e);
        errorOccurred(VfsBundle.message("cannot.create.local.file", e.getMessage()), false);
        return;
      }
      myCancelled.set(false);
      localFile = myLocalFile;
    }
    for (FileDownloadingListener listener : myListeners) {
      listener.downloadingStarted();
    }

    if (myContentProvider == null) {
      myContentProvider = myManager.findContentProvider(myUrl);
    }
    myContentProvider.saveContent(myUrl, localFile, this);
  }

  @Override
  public void finished(@Nullable final FileType fileType) {
    final File localIOFile;

    synchronized (myLock) {
      LOG.debug("Downloading finished, size = " + myLocalFile.length() + ", file type=" + (fileType != null ? fileType.getName() : "null"));
      if (fileType != null) {
        String fileName = myLocalFile.getName();
        int dot = fileName.lastIndexOf('.');
        String extension = fileType.getDefaultExtension();
        if (dot == -1 || !extension.regionMatches(true, 0, fileName, dot + 1, extension.length())) {
          File newFile = FileUtil.findSequentNonexistentFile(myLocalFile.getParentFile(), fileName, extension);
          try {
            FileUtil.rename(myLocalFile, newFile);
            myLocalFile = newFile;
          }
          catch (IOException e) {
            LOG.debug(e);
          }
        }
      }

      localIOFile = myLocalFile;
    }

    VirtualFile localFile = new WriteAction<VirtualFile>() {
      @Override
      protected void run(@NotNull final Result<VirtualFile> result) {
        final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(localIOFile);
        if (file != null) {
          file.refresh(false, false);
        }
        result.setResult(file);
      }
    }.execute().getResultObject();
    LOG.assertTrue(localFile != null, "Virtual local file not found for " + localIOFile.getAbsolutePath());
    LOG.debug("Virtual local file: " + localFile + ", size = " + localFile.getLength());
    synchronized (myLock) {
      myLocalVirtualFile = localFile;
      myPrevLocalFile = null;
      myState = RemoteFileState.DOWNLOADED;
      myErrorMessage = null;
    }
    for (FileDownloadingListener listener : myListeners) {
      listener.fileDownloaded(localFile);
    }
  }

  @Override
  public boolean isCancelled() {
    return myCancelled.get();
  }

  @Override
  public String getErrorMessage() {
    synchronized (myLock) {
      return myErrorMessage;
    }
  }

  @Override
  public void errorOccurred(@NotNull final String errorMessage, boolean cancelled) {
    LOG.debug("Error: " + errorMessage);
    synchronized (myLock) {
      myLocalVirtualFile = null;
      myPrevLocalFile = null;
      myState = RemoteFileState.ERROR_OCCURRED;
      myErrorMessage = errorMessage;
    }
    for (FileDownloadingListener listener : myListeners) {
      if (!cancelled) {
        listener.errorOccurred(errorMessage);
      }
    }
  }

  @Override
  public void setProgressFraction(final double fraction) {
    for (FileDownloadingListener listener : myListeners) {
      listener.progressFractionChanged(fraction);
    }
  }

  @Override
  public void setProgressText(@NotNull final String text, final boolean indeterminate) {
    for (FileDownloadingListener listener : myListeners) {
      listener.progressMessageChanged(indeterminate, text);
    }
  }

  @Override
  public VirtualFile getLocalFile() {
    synchronized (myLock) {
      return myLocalVirtualFile;
    }
  }

  @Override
  public String toString() {
    final String errorMessage = getErrorMessage();
    return "state=" + getState()
           + ", local file=" + myLocalFile
           + (errorMessage != null ? ", error=" + errorMessage : "")
           + (isCancelled() ? ", cancelled" : "");
  }

  @Override
  public RemoteFileState getState() {
    synchronized (myLock) {
      return myState;
    }
  }

  @Override
  public void cancelDownloading() {
    synchronized (myLock) {
      myCancelled.set(true);
      if (myPrevLocalFile != null) {
        myLocalVirtualFile = myPrevLocalFile;
        myLocalFile = VfsUtilCore.virtualToIoFile(myLocalVirtualFile);
        myState = RemoteFileState.DOWNLOADED;
        myErrorMessage = null;
      }
      else {
        myState = RemoteFileState.ERROR_OCCURRED;
      }
    }
    for (FileDownloadingListener listener : myListeners) {
      listener.downloadingCancelled();
    }
  }

  public void refresh(final @Nullable Runnable postRunnable) {
    VirtualFile localVirtualFile;
    synchronized (myLock) {
      localVirtualFile = myLocalVirtualFile;
    }
    final RemoteContentProvider contentProvider = myManager.findContentProvider(myUrl);
    if ((localVirtualFile == null || !contentProvider.equals(myContentProvider) || !contentProvider.isUpToDate(myUrl, localVirtualFile))) {
      myContentProvider = contentProvider;
      addDownloadingListener(new MyRefreshingDownloadingListener(postRunnable));
      restartDownloading();
    }
  }

  private class MyRefreshingDownloadingListener extends FileDownloadingAdapter {
    private final Runnable myPostRunnable;

    public MyRefreshingDownloadingListener(final Runnable postRunnable) {
      myPostRunnable = postRunnable;
    }

    @Override
    public void downloadingCancelled() {
      removeDownloadingListener(this);
      if (myPostRunnable != null) {
        myPostRunnable.run();
      }
    }

    @Override
    public void fileDownloaded(final VirtualFile localFile) {
      removeDownloadingListener(this);
      if (myPostRunnable != null) {
        myPostRunnable.run();
      }
    }

    @Override
    public void errorOccurred(@NotNull final String errorMessage) {
      removeDownloadingListener(this);
      if (myPostRunnable != null) {
        myPostRunnable.run();
      }
    }
  }

  @NotNull
  @Override
  public AsyncResult<VirtualFile> download() {
    synchronized (myLock) {
      switch (getState()) {
        case DOWNLOADING_NOT_STARTED:
          startDownloading();
          return createDownloadedCallback(this);
        case DOWNLOADING_IN_PROGRESS:
          return createDownloadedCallback(this);
        case DOWNLOADED:
          return new AsyncResult.Done<VirtualFile>(myLocalVirtualFile);

        case ERROR_OCCURRED:
        default:
          return new AsyncResult.Rejected<VirtualFile>();
      }
    }
  }

  private static AsyncResult<VirtualFile> createDownloadedCallback(@NotNull final RemoteFileInfo remoteFileInfo) {
    final AsyncResult<VirtualFile> callback = new AsyncResult<VirtualFile>();
    remoteFileInfo.addDownloadingListener(new FileDownloadingAdapter() {
      @Override
      public void fileDownloaded(VirtualFile localFile) {
        try {
          remoteFileInfo.removeDownloadingListener(this);
        }
        finally {
          callback.setDone(localFile);
        }
      }

      @Override
      public void errorOccurred(@NotNull String errorMessage) {
        try {
          remoteFileInfo.removeDownloadingListener(this);
        }
        finally {
          callback.reject(errorMessage);
        }
      }

      @Override
      public void downloadingCancelled() {
        try {
          remoteFileInfo.removeDownloadingListener(this);
        }
        finally {
          callback.setRejected();
        }
      }
    });
    return callback;
  }
}
