#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
#  Copyright 2019 The FATE Authors. All Rights Reserved.
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.
import numpy as np
import functools
import copy
from federatedml.statistic import data_overview


def empty_table_detection(data_instances):
    num_data = data_instances.count()
    if num_data == 0:
        raise ValueError(f"Count of data_instance is 0: {data_instances}")


def empty_feature_detection(data_instances):
    is_empty_feature = data_overview.is_empty_feature(data_instances)
    if is_empty_feature:
        raise ValueError(f"Number of features of DTable is 0: {data_instances}")


def column_gathering(iterable, ):

    lost_columns = set()
    for k, v in iterable:
        features = v.features
        lost_columns.update(np.where(~np.isnan(features))[0])

    return lost_columns


def merge_column_sets(v1: set, v2: set):
    v1_copy = copy.deepcopy(v1)
    v2_copy = copy.deepcopy(v2)
    v1_copy.update(v2_copy)
    return v1_copy


def empty_column_detection(data_instance):

    contains_empty_columns = False
    lost_feat = []
    is_sparse = data_overview.is_sparse_data(data_instance)
    if is_sparse:
        raise ValueError('sparse format empty column detection is not supported for now')
    map_func = functools.partial(column_gathering, )
    map_rs = data_instance.applyPartitions(map_func)
    reduce_rs = map_rs.reduce(merge_column_sets)

    # transform col index to col name
    reduce_rs = np.array(data_instance.schema['header'])[list(reduce_rs)]
    reduce_rs = set(reduce_rs)

    if reduce_rs != set(data_instance.schema['header']):
        lost_feat = list(set(data_instance.schema['header']).difference(reduce_rs))
        contains_empty_columns = True

    if contains_empty_columns:
        raise ValueError('column(s) {} contain(s) no values'.format(lost_feat))


def check_legal_schema(schema):
    # check for repeated header & illegal/non-printable chars except for space
    # allow non-ascii chars
    if schema is None:
        return
    header = schema.get("header", None)
    if header is not None:
        for col_name in header:
            if not col_name.isprintable():
                raise ValueError(f"non-printable char found in header column {col_name}, please check.")
        header_set = set(header)
        if len(header_set) != len(header):
            raise ValueError(f"data header contains repeated values, please check.")

    sid_name = schema.get("sid_name", None)
    if sid_name is not None and not sid_name.isprintable():
        raise ValueError(f"non-printable char found in sid_name {sid_name}, please check.")

    label_name = schema.get("label_name", None)
    if label_name is not None and not label_name.isprintable():
        raise ValueError(f"non-printable char found in label_name {label_name}, please check.")

    if header is not None:
        if sid_name is None and label_name is None:
            if len(set(header)) != len(header):
                raise ValueError(f"Repeated names found in 'header', please check.")
        else:
            if len(set(header) | {sid_name, label_name}) != len(header) + len([sid_name, label_name]):
                raise ValueError(f"Repeated names found in ('header', 'sid_name', 'label_name'), please check.")
    else:
        if sid_name == label_name:
            raise ValueError(f"Same names given for 'sid_name' and 'label_name', please check.")

@@ -654,16 +654,17 @@
 icense.%0A
+%0A
 import n
@@ -751,16 +751,52 @@
 verview%0A
+from federatedml.util import LOGGER%0A
 %0A%0Adef em
@@ -2549,16 +2549,56 @@
 i chars%0A
+    LOGGER.debug(f%22schema is %7Bschema%7D%22)%0A
     if s
@@ -2604,32 +2604,32 @@
 schema is None:%0A
-
         return%0A 
@@ -2663,24 +2663,64 @@
 der%22, None)%0A
+    LOGGER.debug(f%22header is %7Bheader%7D%22)%0A
     if heade
@@ -3116,24 +3116,68 @@
 ame%22, None)%0A
+    LOGGER.debug(f%22sid_name is %7Bsid_name%7D%22)%0A
     if sid_n
@@ -3361,24 +3361,72 @@
 ame%22, None)%0A
+    LOGGER.debug(f%22label_name is %7Blabel_name%7D%22)%0A
     if label
@@ -3605,211 +3605,8 @@
 ne:%0A
-        if sid_name is None and label_name is None:%0A            if len(set(header)) != len(header):%0A                raise ValueError(f%22Repeated names found in 'header', please check.%22)%0A        else:%0A    
     
@@ -3639,28 +3639,16 @@
 sid_name
-, label_name
 %7D) != le
@@ -3676,28 +3676,12 @@
 name
-, label_name%5D):%0A    
+%5D):%0A
     
@@ -3756,22 +3756,8 @@
 ame'
-, 'label_name'
 ), p

allow label name in header