import os
import numpy as np
from math import log, e
from pathlib import Path
import shutil


def bytes_from_file(filename, chunk_size=256):
    try:
        all_chucnks = []
        with open(filename, "rb") as f:
            while True:
                chunk = f.read(chunk_size)
                if chunk:
                    all_chucnks.append(chunk)
                else:
                    break

        data = {}
        count = 0
        for i in range(len(all_chucnks)):
            if i < len(all_chucnks) - 1:
                d = [b for b in all_chucnks[i]] + [b for b in all_chucnks[i+1]]
                data[count] = d
                count += 1
        return data
    except FileNotFoundError:
        print('File not found')
    except:
        print('Something went wrong')

def get_entropy(labels, base=None):
    """ Computes entropy of label distribution. """

    n_labels = len(labels)

    if n_labels <= 1:
        return 0

    value, counts = np.unique(labels, return_counts=True)
    probs = counts / n_labels

    ent = 0.

    # Compute entropy
    base = e if base is None else base
    for i in probs:
        ent -= i * log(i, base)

    return round(ent, 6)

def read_data(write=False, chunk_size=256):
    cd = '/Users/parnikade/Documents/Pota/SJSU/fall20/Coding'
    dir = os.path.join(cd, 'entropy_samples_' + str(chunk_size * 2))
    if os.path.exists(dir):
        shutil.rmtree(dir)
    Path(dir).mkdir(parents=True, exist_ok=True)
    print('Created /entropy_samples')
    for root, dirs, files in os.walk(
            os.path.join(cd, 'labeled_samples')):
        for d in dirs:
            bot_dir = os.path.join(dir, d)
            Path(bot_dir).mkdir(parents=True, exist_ok=True)
        for file in files:
            if not file.startswith('.')\
                    and os.path.isfile(os.path.join(root, file)):
                file_path = os.path.join(root, file)
                d = dir + '/' + root.split('/')[-1]
                file_data = bytes_from_file(file_path, chunk_size)
                entropy = []
                for k, v in file_data.items():
                    entropy.append(get_entropy(v, 2))
                if write:
                    with open(d + '/' + file, 'w') as file_handle:
                        for ent in entropy:
                            file_handle.write('%f\n' % ent)
                else:
                    print(entropy)
            print('Done for ' + file)


def main():
    read_data(write=True, chunk_size=256)
    read_data(write=True, chunk_size=128)


if __name__ == '__main__':
    main()