/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 utils

import (
	"io"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"

	"github.com/apache/incubator-openwhisk-wskdeploy/wskprint"
)

// check if the path represents file path or dir path
func isFilePath(path string) bool {
	// when split returns dir and file, splitting path on the final "/"
	// check if file is not empty to classify that path as a file path
	_, file := filepath.Split(path)
	if len(file) == 0 {
		return false
	}
	return true
}

// check if the given path exists as a file
func isFile(path string) (bool, error) {
	var err error
	var info os.FileInfo
	// run stat on the file and if the it returns no error,
	// read the fileInfo to check if its a file or not
	if info, err = os.Stat(path); err == nil {
		if info.Mode().IsRegular() {
			return true, nil
		}
	}
	// stat returned an error and here we are chekcking if it was os.PathError
	if !os.IsNotExist(err) {
		return false, nil
	}
	// after running through all the possible checks, return false and an err
	return false, err
}

// copy one single source file to the destination path
func copyFile(src, dst string) error {
	var err error
	var sourceFD *os.File
	var destFD *os.File
	var srcInfo os.FileInfo
	var srcDirInfo os.FileInfo

	wskprint.PrintlnOpenWhiskVerbose(Flags.Verbose, "Source File ["+src+"] is being copied to ["+dst+"]")

	// open source file to read it from disk and defer to close the file
	// once this function is done executing
	if sourceFD, err = os.Open(src); err != nil {
		return err
	}
	defer sourceFD.Close()

	// running stat on Dir(src), Dir returns all but the last element of the src
	// this info is needed in case when a destination path has a directory structure which does not exist
	if srcDirInfo, err = os.Stat(filepath.Dir(src)); err != nil {
		return err
	}

	// check if the parent directory exist before creating a destination file
	// create specified path along with creating any parent directory
	// e.g. when destination is greeting/common/utils.js and parent dir common
	// doesn't exist, its getting created here at greeting/common
	if _, err = os.Stat(filepath.Dir(dst)); os.IsNotExist(err) {
		wskprint.PrintlnOpenWhiskVerbose(Flags.Verbose, "Creating directory pattern ["+filepath.Dir(dst)+"] before creating destination file")
		if err = os.MkdirAll(filepath.Dir(dst), srcDirInfo.Mode()); err != nil {
			return err
		}
	}

	// create destination file before copying source content
	// defer closing the destination file until the function is done executing
	if destFD, err = os.Create(dst); err != nil {
		return err
	}
	defer destFD.Close()

	// now, actually copy the source file content into destination file
	if _, err = io.Copy(destFD, sourceFD); err != nil {
		return err
	}

	// retrieve the file mode bits of the source file
	// so that the bits can be set to the destination file
	if srcInfo, err = os.Stat(src); err != nil {
		return err
	}
	return os.Chmod(dst, srcInfo.Mode())
}

// recursively copy the entire source directory to destination path
func copyDir(src, dst string) error {
	var err error
	var fileDescriptors []os.FileInfo
	var srcInfo os.FileInfo

	// retrieve os.fileInfo of the source directory
	if srcInfo, err = os.Stat(src); err != nil {
		return err
	}

	// create destination directory with parent directories
	if err = os.MkdirAll(dst, srcInfo.Mode()); err != nil {
		return err
	}

	// now, retrieve all the directory/file entries under the source directory
	if fileDescriptors, err = ioutil.ReadDir(src); err != nil {
		return err
	}

	// iterating over the entire list of files/directories under the destination path
	// run copyFile or recursive copyDir based on if its file or dir
	for _, fd := range fileDescriptors {
		srcFilePath := path.Join(src, fd.Name())
		dstFilePath := path.Join(dst, fd.Name())

		if fd.IsDir() {
			if err = copyDir(srcFilePath, dstFilePath); err != nil {
				return err
			}
		} else {
			if err = copyFile(srcFilePath, dstFilePath); err != nil {
				return err
			}
		}
	}
	return nil
}
