import ast
import os

class database:
	def __init__(self, Apath):  # setting object path to path
		self.path = Apath
		if self.is_valid_path():
			p = Apath.split('.')
			if p[1] != 'pf':
				self.ValueError_func(f"File has to have PyFetch extension (pf), not ({p[1]})")
		else:
			self.FileNotFoundError_func(f"Path is not valid: {self.path}")

	##### ERRORS #####

	def FileNotFoundError_func(self, details):
		raise FileNotFoundError(f"\n\n{details}\n")

	def generic_exception(self, details):
		raise Exception(f"\n\n{details}\n")

	def TypeError_func(self, details):
		raise TypeError(f"\n\n{details}\n")

	def IndexError_func(self, details):
		raise IndexError(f"\n\n{details}\n")

	def ValueError_func(self, details):
		raise ValueError(f"\n\n{details}\n")

	##### ERRORS #####

	def count_lines(self):
		count = 0
		with open(self.path, 'r') as file:
			lines = file.readlines()
		for line in lines:
			count += 1
		return count


	def line_num_through_id(self, id):  # returns the line number corresponding with the id
		count = 0
		with open(self.path, 'r') as file:
			lines = file.readlines()
		for line in lines:
			if int(line.split("---")[0]) == id:
				return count
			else:
				count += 1
		self.IndexError_func(f"Id ({str(id)}) not found.")


	def is_valid_path(self):  # there must always be a dot for the extension, eg: .txt, .exe, .dll, .mp3
		if '.' not in self.path:
			return False
		else:
			return True


	def make(self):  # creates db if not exists
		if self.is_valid_path():  # check if path is valid
			if not os.path.exists(self.path):  # check if file exists, and if it doesn't:
				open(self.path, 'a').close()  # open then close right after to make empty file
		else:
			self.FileNotFoundError_func(f"Path is not valid: {self.path}")


	def insert(self, dic):  # inserts to db (has to be a dictionary)
		if str(type(dic)) == "<class 'dict'>":  # ensures input is a dictionary
			try:
				line_num = str(self.count_lines())
				with open(self.path, 'a') as file:
					file.write(f"{line_num}---{str(dic)}\n")
			except FileNotFoundError:
				self.FileNotFoundError_func(f"The file doesn't exist or wasn't found, use the make() method to make a new database.\n{self.path}")
		else:
			self.TypeError_func("Input has to be a dictionary.")


	def query(self, id):  # query's database and returns line corresponding to the line id
		if str(type(id)) == "<class 'int'>":  # making sure id is an integer
			try:
				with open(self.path, 'r') as file:
					lines = file.readlines()
				for line in lines:
					content = line.split('---')  # separating id and dictionary in line
					if int(content[0]) == id:
						return ast.literal_eval(content[1])
				self.IndexError_func(f"id ({str(id)}) not found")
			except FileNotFoundError:
				self.FileNotFoundError_func(f"The file doesn't exist or wasn't found, use the make() method to make a new database.\n{self.path}")
		else:
			self.TypeError_func(f"Id has to be an integer, not {str(type(id))}")


	def remove(self, id):  # removes line corresponding to the id
		if str(type(id)) == "<class 'int'>":  # making sure id is an integer
			try:
				with open(self.path, 'r') as file:
					contents = file.readlines()
				for line in contents:
					line = line.split('---')
					if int(line[0]) == id:
						del contents[self.line_num_through_id(id)]
						with open(self.path, 'w') as file:
							for line in contents:
								file.write(line)  # rewriting lines to file
							return
				self.IndexError_func(f"Id ({str(id)}) not found.")
			except FileNotFoundError:
				self.FileNotFoundError_func(f"The file doesn't exist or wasn't found, use the make() method to make a new database.\n{self.path}")
		else:
			self.TypeError_func(f"Id has to be an integer, not {str(type(id))}")


	def fetch_all(self):  # returns all dictionaries in a list
		try:
			with open(self.path, 'r') as file:
				raw = file.readlines()
			contents = []
			for line in raw:
				contents.append(ast.literal_eval(line.split('---')[1]))
			return contents
		except FileNotFoundError:
			self.FileNotFoundError_func(f"The file doesn't exist or wasn't found, use the make() method to make a new database.\n{self.path}")


	def re_id(self):  # reformats the file to have corrects id's
		try:
			with open(self.path, 'r') as file:
				raw = file.readlines()
				contents = []
			for count, line in enumerate(raw):
				contents.append(str(count) + "---" + line.split("---")[1])
			with open(self.path, 'w') as file:
				for line in contents:
					file.write(line)
		except FileNotFoundError:
			self.FileNotFoundError_func(f"The file doesn't exist or wasn't found, use the make() method to make a new database.\n{self.path}")


	def overwrite(self):  # overwrites database or creates new one if not exist
		if self.is_valid_path():  # check if path is valid
			open(self.path, 'w').close()  # open then close right after to make empty file and overwrites if already exist
		else:
			self.FileNotFoundError_func(f"Path is not valid: {self.path}")