package com.codegym.task.task20.task2022;

import java.io.*;
import java.util.Objects;

/*
Overriding serialization in a thread

*/

public class Solution implements Serializable, AutoCloseable {
    //Write the verification code yourself in the main method:
    //1) create an instance of the Solution class
    //2) write data to it (writeObject)
    //3) serialize the Solution class (writeObject(ObjectOutputStream out))
    //4) deserialize, get a new object
    //5) write data to the new object (writeObject)
    //6) verify that the file contains the data from Items 2 and 5
    public static void main(String[] args) throws Exception {
        //FIXME: how to prevent StreamCorruptedException? => first create out then in
        String fileName = "/Users/lilianetop/Desktop/task2022.txt";
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(fileName));
        ObjectInputStream in = new ObjectInputStream(new FileInputStream(fileName));

        Solution solution = new Solution(fileName);
        //solution.writeObject("What will happen?");
        System.out.println(solution.toString());//how to get the text back?

        out.writeObject(solution);
        out.flush();//why do this? is it necessary?


        Solution solution1 = (Solution) in.readObject();
        //solution1.writeObject("This text is NOT disappearing");
        System.out.println((solution1.toString()));//it shows the memory location of the object but doesn't show the string
        solution.close();

        System.out.println(solution.equals(solution1));//returns false even if I remove the first and second string why?
    }

    //1. The stream field must be declared with the transient modifier.
    transient private FileOutputStream stream;
    private String fileName;

    public Solution() {
    }

    //5. In the Solution class constructor, the stream field must be initialized with a new FileOutputStream object with the argument (fileName).
    public Solution(String fileName) throws FileNotFoundException {
        this.fileName = fileName;
        this.stream = new FileOutputStream(fileName);
    }
    public void writeObject(String string) throws IOException {
        stream.write(string.getBytes());
        stream.write("\n".getBytes());
        stream.flush();
    }
//2. The writeObject(ObjectOutputStream out) method should not call the close method on the stream passed as an argument.
    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
        //out.close();
    }
//3. The readObject(ObjectInputStream in) method should not call the close method on the stream passed as an argument.
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        //4. In the readObject(ObjectInputStream in) method, the stream field must be initialized
        // with a new FileOutputStream object using the arguments (fileName, true).
        in.defaultReadObject();
        stream = new FileOutputStream(fileName, true);


        //in.close();
    }

    @Override
    public void close() throws Exception {
        System.out.println("Closing everything!");
        stream.close();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Solution)) return false;
        Solution solution = (Solution) o;
        return stream.equals(solution.stream);
    }

    @Override
    public int hashCode() {
        return Objects.hash(stream);
    }
}