# Copyright 2022 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import collections
import json
import re


def re_from_string_or_list(input):
    if input is None:
        return None
    re_str = input if isinstance(input, str) else "|".join(input)
    return re.compile(re_str)


class BucketMatch(object):
    def __init__(self, name, process, vmo):
        self.name = name
        self.process = re_from_string_or_list(process)
        self.vmo = re_from_string_or_list(vmo)


class Bucket(object):
    def __init__(self, name):
        self.name = name
        self.processes = collections.defaultdict(list)
        self.size = 0


class Digest(object):
    @classmethod
    def FromMatchSpecs(cls, snapshot, match_specs):
        return Digest(
            snapshot, [BucketMatch(m[0], m[1], m[2]) for m in match_specs]
        )

    @classmethod
    def FromJSON(cls, snapshot, match_json):
        return Digest(
            snapshot,
            [
                BucketMatch(
                    m["name"],
                    m["process"] if "process" in m else None,
                    m["vmo"] if "vmo" in m else None,
                )
                for m in match_json
            ],
        )

    @classmethod
    def FromJSONFile(cls, snapshot, match_file):
        return cls.FromJSON(snapshot, json.load(match_file))

    @classmethod
    def FromJSONString(cls, snapshot, match_string):
        return cls.FromJSON(snapshot, json.loads(match_string))

    @classmethod
    def FromJSONFilename(cls, snapshot, match_filename):
        with open(match_filename) as match_file:
            return cls.FromJSONFile(snapshot, match_file)

    def __init__(self, snapshot, bucket_matches):
        self.buckets = {bm.name: Bucket(bm.name) for bm in bucket_matches}
        undigested_vmos = snapshot.vmos.copy()
        # Each VMO will be assigned to at most one bucket. Precedence follows
        # the order of bucket_matches.
        for process in snapshot.processes.values():
            for bm in bucket_matches:
                if bm.process and not bm.process.fullmatch(process.name):
                    continue
                for vmo in process.vmos:
                    if vmo.koid not in undigested_vmos:
                        continue
                    if bm.vmo and not bm.vmo.fullmatch(vmo.name):
                        continue
                    if vmo.committed_bytes == 0:
                        continue
                    self.buckets[bm.name].processes[(process,)].append(vmo)
                    self.buckets[bm.name].size += vmo.committed_bytes
                    del undigested_vmos[vmo.koid]

        undigested = Bucket("Undigested")
        # For the Undigested bucket, we want to store VMOs by "sharing pools"
        # That is, the keys to undigested.processes will be a set of process
        # names that map to the list of VMOs they all share.
        vmos_to_processes = collections.defaultdict(list)
        for process in snapshot.processes.values():
            for v in filter(lambda v: v.koid in undigested_vmos, process.vmos):
                vmos_to_processes[v.koid].append(process)

        for vmo_koid, processes in vmos_to_processes.items():
            processes.sort(key=lambda p: p.full_name)
            vmo = snapshot.vmos[vmo_koid]
            if vmo.committed_bytes == 0:
                continue
            undigested.processes[tuple(processes)].append(vmo)
            undigested.size += vmo.committed_bytes
        self.buckets["Undigested"] = undigested

        kernel = Bucket("Kernel")
        kernel.size = (
            snapshot.kernel.wired
            + snapshot.kernel.total_heap
            + snapshot.kernel.mmu
            + snapshot.kernel.ipc
            + snapshot.kernel.other
        )
        self.buckets["Kernel"] = kernel
        orphaned = Bucket("Orphaned")
        orphaned.size = snapshot.orphaned
        self.buckets["Orphaned"] = orphaned
