class VolumePermissionEnricher extends BaseEnricher {

    @Override
    public void enrich(PlatformMode platformMode, KubernetesListBuilder builder) {

        builder.accept(new TypedVisitor<PodTemplateSpecBuilder>() {
            @Override
            public void visit(PodTemplateSpecBuilder builder) {
                PodSpec podSpec = builder.buildSpec();
                if (podSpec == null) {
                    return;
                }

                if (!checkForPvc(podSpec)) {
                    return;
                }

                List<Container> containers = podSpec.getContainers();
                if (containers == null || containers.isEmpty()) {
                    return;
                }

                log.verbose("Adding init container for changing persistent volumes access mode to %s",
                        getConfig(Config.permission));
                if (!initContainerHandler.hasInitContainer(builder, ENRICHER_NAME)) {
                    initContainerHandler.appendInitContainer(builder, createPvInitContainer(podSpec));
                }
            }

            private boolean checkForPvc(PodSpec podSpec) {
                List<Volume> volumes = podSpec.getVolumes();
                if (volumes != null) {
                    for (Volume volume : volumes) {
                        PersistentVolumeClaimVolumeSource persistentVolumeClaim = volume.getPersistentVolumeClaim();
                        if (persistentVolumeClaim != null) {
                            return true;
                        }
                    }
                }
                return false;
            }

            private Container createPvInitContainer(PodSpec podSpec) {
                Map<String, String> mountPoints = extractMountPoints(podSpec);
                return new ContainerBuilder()
                        .withName(ENRICHER_NAME)
                        .withImage("busybox")
                        .withImagePullPolicy("IfNotPresent")
                        .withCommand(createChmodCommandArray(mountPoints))
                        .withVolumeMounts(createMounts(mountPoints))
                        .build();
            }

            private List<String> createChmodCommandArray(Map<String, String> mountPoints) {
                List<String> ret = new ArrayList<>();
                ret.add("chmod");
                ret.add(getConfig(Config.permission));
                Set<String> uniqueNames = new LinkedHashSet<>(mountPoints.values());
                for (String name : uniqueNames) {
                    ret.add(name);
                }
                return ret;
            }

            private List<VolumeMount> createMounts(Map<String, String> mountPoints) {
                List<VolumeMount> ret = new ArrayList<>();
                for (Map.Entry<String, String> entry : mountPoints.entrySet()) {
                    JsonObject mount = new JsonObject();
                    mount.add("name", new JsonPrimitive(entry.getKey()));
                    mount.add("mountPath", new JsonPrimitive(entry.getValue()));

                    VolumeMount volumeMount = new VolumeMountBuilder()
                            .withName(entry.getKey())
                            .withMountPath(entry.getValue())
                            .build();
                    ret.add(volumeMount);
                }
                return ret;
            }

            private Map<String, String> extractMountPoints(PodSpec podSpec) {
                Map<String, String> nameToMount = new LinkedHashMap<>();

                List<Volume> volumes = podSpec.getVolumes();
                if (volumes != null) {
                    for (Volume volume : volumes) {
                        PersistentVolumeClaimVolumeSource persistentVolumeClaim = volume.getPersistentVolumeClaim();
                        if (persistentVolumeClaim != null) {
                            String name = volume.getName();
                            String mountPath = getMountPath(podSpec.getContainers(), name);

                            nameToMount.put(name, mountPath);
                        }
                    }
                }
                return nameToMount;
            }

            private String getMountPath(List<Container> containers, String name){
                for (Container container : containers) {
                    List<VolumeMount> volumeMounts = container.getVolumeMounts();
                    if (volumeMounts != null) {
                        for (VolumeMount volumeMount : volumeMounts) {
                            if (name.equals(volumeMount.getName())){
                                return volumeMount.getMountPath();
                            }
                        }
                    }
                }
                throw new IllegalArgumentException("No matching volume mount found for volume "+ name);
            }

        });

        builder.accept(new TypedVisitor<PersistentVolumeClaimBuilder>() {
            @Override
            public void visit(PersistentVolumeClaimBuilder pvcBuilder) {
                // lets ensure we have a default storage class so that PVs will get dynamically created OOTB
                if (pvcBuilder.buildMetadata() == null) {
                    pvcBuilder.withNewMetadata().endMetadata();
                }
                String storageClass = getConfig(Config.defaultStorageClass);
                if (StringUtils.isNotBlank(storageClass) && !pvcBuilder.buildMetadata().getAnnotations().containsKey(VOLUME_STORAGE_CLASS_ANNOTATION)) {
                    pvcBuilder.editMetadata().addToAnnotations(VOLUME_STORAGE_CLASS_ANNOTATION, storageClass).endMetadata();
                }
            }
        });
    }

    public  VolumePermissionEnricher(MavenEnricherContext buildContext);

}