#!/usr/bin/env python3
import glob
import os
import sys
import pwd
import shutil
import signal
import platform
from datetime import datetime

def print_files(args):
  files = []

  if len(args) == 1 or args[1] == "":
    files = glob.glob("*")
  else:
    try:
      files = os.listdir(args[1])
    except:
      pass

  for file in files:
    if os.path.isdir(file):
      print(" dir: " + file)
    else:
      print("file: " + file)

def print_info(args):
  filename = args[1]
  if len(args) == 1 or filename == " " or filename == "":
    print("error: info <file or dir>")
    return

  if not os.path.exists(filename):
    print("error: " + filename + " does not exist.")
    return 

  output = ""
  
  # file or directory
  is_directory = os.path.isdir(filename)
  if is_directory: 
    output += "Type => {}\n".format("Directory")
  else:
    output += "Type => {}\n".format("File")

  # owner
  owner = pwd.getpwuid(os.stat(filename).st_uid).pw_name
  output += "Owner => {}\n".format(owner)

  # last modified time
  last_modified = datetime.utcfromtimestamp(
    round(int(os.path.getmtime(filename)))).strftime('%b %d %Y %H:%M:%S')
  output += "Last modified => {}\n".format(last_modified)

  if not is_directory:
    size = os.path.getsize(filename)
    output += "Size (Bytes) => {}\n".format(size)

    executable = os.access(filename, os.X_OK)
    output += "Executable => {}\n".format(executable)

  print(output)

def delete_file(args):
  filename = args[1]
  if len(args) == 1 or filename == " " or filename == "":
    print("error: delete <file or dir>")
    return

  if not os.path.exists(filename):
    print("error: " + filename + " does not exist.")
    return 

  if os.path.isdir(filename):
    os.rmdir(filename)
  else:
    os.remove(filename)
    
def copy_file(args):
  if len(args) < 3:
    print("error: copy <src> <dest>")
    return
  
  src = args[1]
  dest = args[2]

  if not os.path.exists(src):
    print("error: {} does not exist".format(src))
    return

  if os.path.exists(dest):
    print("error: destination {} exists".format(src))
    return

  # create file
  with open(dest, 'w'): pass

  # copy contents src => dest
  shutil.copy(src, dest)
  print("copied!")

def change_dir(direction, args):
  if direction == "up":
    if os.getcwd() == "/":
      print("cannot go up anymore...")
      return
    os.chdir("../")
  elif direction == "down":
    # no directory to cd into provided
    if len(args) == 1:
      print("down <dir>")
      return

    if os.path.exists(args[1]):
      os.chdir(args[1])
    else:
      print("error: " + args[1] + " does not exist")

def run(args):
  if args[0] == "":
    return

  ex = add_path(args[0])
  if not ex:
    print("error: not executable")
    return 
  
  try:
    pid = os.fork()
    if pid == 0:
      os.execv(ex, args)
      os._exit(0) # just-in-case
    else:
      # interrupt from keyboard
      signal.signal(signal.SIGINT, lambda *args: None)
      
      _, status = os.waitpid(pid, 0)
      exit_code = os.WEXITSTATUS(status)
      print("\nProcess exited with " + str(exit_code))
      
      signal.signal(signal.SIGINT, lambda *args: quit())

  except OSError as e:
    print("Error executing command")
    print(e)

def add_path(cmd):
  if cmd[0] not in ['/', '.']:
    for d in ["/bin/", "/usr/bin/", "/usr/local/bin/", "./"]:
      execname = d + cmd 
      if os.path.isfile(execname) and os.access(execname, os.X_OK):
        return execname 
    return False
  else:
    return cmd  

def make(args, type):
  if len(args) < 2:
    if type == "dir":
      print("makedir <filename>")
    else:
      print("make <filename>")
    return

  name = args[1]
  if os.path.exists(name):
    print("error: " + name + " exists.")
    return

  if type == "dir":
    os.mkdir(name)
  else:
    with open(name, 'w'): pass

def clear_screen():
  # mac or linux
  if os.name == "posix" or platform.system() == "Linux":
    os.system('clear')
    return
  else:
    os.system('cls')
    return

def quit():
  sys.exit("\n-- Exiting shell --")
  return

while True:
  read = None
  try:
    read = input("> ")
  except EOFError:
    quit()
  except KeyboardInterrupt:
    quit()

  args = read.split(" ")
  if args[0] == "files":
    print_files(args)
  elif args[0] == "info":
    print_info(args)
  elif args[0] == "delete":
    delete_file(args)
  elif args[0] == "copy":
    copy_file(args)
  elif args[0] == "where":
    print(os.getcwd())
  elif args[0] == "up":
    change_dir("up", args)
  elif args[0] == "down":
    change_dir("down", args)
  elif args[0] == "finish":
    quit()
  elif args[0] == "clear":
    clear_screen()
  elif args[0] == "make":
    make(args, "file")
  elif args[0] == "makedir":
    make(args, "dir")
  elif args[0] == "help":
    print("""
    ---- HELP ----
    > files
    > info <file or dir>
    > files <optional dir>
    > delete <file or dir>
    > copy <src> <dest>
    > make <filename>
    > makedir <dirname>
    > where 
    > up
    > down <dir>
    > <executable> <arguments>
    > finish
    > clear

    """)
  else:
    run(args)
