<commit_before>package gobioinfo

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

type FASTQRead struct {
	Sequence string
	Quality  string
	Name     string
	Misc     string
}

type FASTQScanner struct {
	*os.File
	*bufio.Scanner
}

func NewFASTQScanner(filePath string) FASTQScanner {

	file, err := os.Open(filePath)

	if err != nil {
		fmt.Println("error opening file= ", err)
		os.Exit(1)
	}
	fastqscanner := FASTQScanner{Scanner: bufio.NewScanner(file), File: file}
	return (fastqscanner)
}

func (s *FASTQScanner) Close() {
	s.File.Close()
	fmt.Println("closing fastqscanner")
}

func (s *FASTQScanner) NextRead() FASTQRead {

	var ln1, ln2, ln3, ln4 string
	var newRead FASTQRead

	if s.Scanner.Scan() {
		ln1 = s.Scanner.Text()
		fmt.Print(ln1)
	} else {
		return FASTQRead{}
	}
	if s.Scanner.Scan() {
		ln2 = s.Scanner.Text()
	} else {
		return FASTQRead{}
	}
	if s.Scanner.Scan() {
		ln3 = s.Scanner.Text()
	} else {
		return FASTQRead{}
	}
	if s.Scanner.Scan() {
		ln4 = s.Scanner.Text()
	} else {
		return FASTQRead{}
	}

	newRead = FASTQRead{Name: ln1, Sequence: ln2, Misc: ln3, Quality: ln4}

	return newRead

}

type FASTQWriter struct {
	*os.File
	*bufio.Writer
}

func NewFASTQWriter(filePath string) FASTQWriter {

	file, err := os.Create(filePath)

	if err != nil {
		fmt.Println("error opening file= ", err)
		os.Exit(1)
	}
	fastqwriter := FASTQWriter{Writer: bufio.NewWriter(file), File: file}
	return (fastqwriter)
}

func (w *FASTQWriter) Write(r FASTQRead) error {
	//compose FASTQRead struct into the proper format

	for_writing := strings.Join([]string{"@" + r.Name, r.Sequence, r.Misc, r.Quality, ""}, "\n")
	fmt.Println(for_writing)
	//check if there are enough bytes lefts in the writer buffer
	var err error
	var i int
	if w.Writer.Available() < len(for_writing) {
		w.Writer.Flush()

		//flush the write buffer, then write
		_, err = w.Writer.WriteString(for_writing)
	} else {
		fmt.Println("here")
		//write to the write buffer
		i, err = w.Writer.WriteString(for_writing)
		fmt.Println("return from writestring: ", i)
		fmt.Println("here")
	}
	return (err)
}

func (w *FASTQWriter) Close() {
	w.Writer.Flush()
	w.File.Close()
	fmt.Println("closing the writer")
}

/*

NOTE...there is a lot of repetitive code here (between FASTA and FASTQ).
TODO: look into a better way of doing this a bit...they both have the same
functions, they only differ in the exact string that is passed to the io buffer
<commit_msg>elaborating on the fastq writer<commit_after>package gobioinfo

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

type FASTQRead struct {
	Sequence string
	Quality  string
	Name     string
	Misc     string
}

type FASTQScanner struct {
	*os.File
	*bufio.Scanner
}

func NewFASTQScanner(filePath string) FASTQScanner {

	file, err := os.Open(filePath)

	if err != nil {
		fmt.Println("error opening file= ", err)
		os.Exit(1)
	}
	fastqscanner := FASTQScanner{Scanner: bufio.NewScanner(file), File: file}
	return (fastqscanner)
}

func (s *FASTQScanner) Close() {
	s.File.Close()
	fmt.Println("closing fastqscanner")
}

func (s *FASTQScanner) NextRead() FASTQRead {

	var ln1, ln2, ln3, ln4 string
	var newRead FASTQRead

	if s.Scanner.Scan() {
		ln1 = s.Scanner.Text()
		fmt.Print(ln1)
	} else {
		return FASTQRead{}
	}
	if s.Scanner.Scan() {
		ln2 = s.Scanner.Text()
	} else {
		return FASTQRead{}
	}
	if s.Scanner.Scan() {
		ln3 = s.Scanner.Text()
	} else {
		return FASTQRead{}
	}
	if s.Scanner.Scan() {
		ln4 = s.Scanner.Text()
	} else {
		return FASTQRead{}
	}

	newRead = FASTQRead{Name: ln1, Sequence: ln2, Misc: ln3, Quality: ln4}

	return newRead

}

//defines the FASTQWriter structure, which contains a pointer to the file to 
//which FASTQReads will be written and to a bufio.Writer instance
type FASTQWriter struct {
	*os.File
	*bufio.Writer
}

//creates a new FASTQWriter instance, which contains the file and writer objects
//from a file path string
func NewFASTQWriter(filePath string) FASTQWriter {

	file, err := os.Create(filePath)

	if err != nil {
		fmt.Println("error opening file= ", err)
		os.Exit(1)
	}
	fastqwriter := FASTQWriter{Writer: bufio.NewWriter(file), File: file}
	return (fastqwriter)
}

//writes a FASTQRead to file, returns an error
func (w *FASTQWriter) Write(r FASTQRead) error {
	
	//compose FASTQRead struct into the proper format
	for_writing := strings.Join([]string{"@" + r.Name, r.Sequence, r.Misc,
							 	r.Quality, ""}, "\n")
	fmt.Println(for_writing)
	
	var err error
	var i int
	
	//check if there are enough bytes lefts in the writer buffer
	if w.Writer.Available() < len(for_writing) {
		
		//flush the write buffer
		w.Writer.Flush()

		//then write the current read to the buffer
		_, err = w.Writer.WriteString(for_writing)
	} else {
		//write to the write buffer
		i, err = w.Writer.WriteString(for_writing)
		fmt.Println("return from writestring: ", i)
	}
	//returns any write error that might have occurred
	return (err)
}

//closes the FASTQWriter
func (w *FASTQWriter) Close() {
	w.Writer.Flush()
	w.File.Close()
	fmt.Println("closing the writer")
}

/*

NOTE...there is a lot of repetitive code here (between FASTA and FASTQ).
TODO: look into a better way of doing this a bit...they both have the same
functions, they only differ in the exact string that is passed to the io buffer

{'fraction_non_alphanumeric': 0.12410003789314134, 'fraction_numerical': 0.005683971201212581, 'mean_word_length': 3.675819309123118, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3445063', 'n_tokens_mistral': 2109, 'n_tokens_neox': 1998, 'n_words': 568}