/*
 *   Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 *   WSO2 Inc. licenses this file to you 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.
 *
 */
package org.wso2.carbon.device.mgt.mobile.impl.ios;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.Feature;
import org.wso2.carbon.device.mgt.common.FeatureManager;
import org.wso2.carbon.device.mgt.mobile.impl.ios.dao.IOSDAOFactory;
import org.wso2.carbon.device.mgt.mobile.impl.ios.dao.MobileDeviceManagementDAOException;
import org.wso2.carbon.device.mgt.mobile.impl.ios.dao.MobileDeviceManagementDAOFactory;
import org.wso2.carbon.device.mgt.mobile.impl.ios.dao.MobileFeatureDAO;
import org.wso2.carbon.device.mgt.mobile.impl.ios.dto.MobileFeature;
import org.wso2.carbon.device.mgt.mobile.impl.ios.util.MobileDeviceManagementUtil;

import java.util.ArrayList;
import java.util.List;

public class IOSFeatureManager implements FeatureManager {

    private static final Log log = LogFactory.getLog(IOSFeatureManager.class);
    private MobileDeviceManagementDAOFactory mobileDeviceManagementDAOFactory;

    private MobileFeatureDAO featureDAO;

    public IOSFeatureManager() {
        mobileDeviceManagementDAOFactory = new IOSDAOFactory();
        this.featureDAO = mobileDeviceManagementDAOFactory.getMobileFeatureDAO();
    }

    public boolean addFeature(Feature feature) throws DeviceManagementException {
        try {
            IOSDAOFactory.beginTransaction();
            MobileFeature mobileFeature = MobileDeviceManagementUtil.convertToMobileFeature(feature);

            try {
                featureDAO.addFeature(mobileFeature);
            } catch (MobileDeviceManagementDAOException e) {
                log.error("error in feature add ", e);
                throw new DeviceManagementException("error in feature add", e);
            }
            IOSDAOFactory.commitTransaction();
            return true;
        } catch (MobileDeviceManagementDAOException e) {
            try {
                IOSDAOFactory.rollbackTransaction();
            } catch (MobileDeviceManagementDAOException e1) {
                log.warn("Error occurred while roll-backing the transaction", e);
            }
            throw new DeviceManagementException("DB transaction error occurred while add the feature", e);
        }
    }

    public Feature getFeature(String code) throws DeviceManagementException {
        try {
            MobileFeature mobileFeature = featureDAO.getFeatureByCode(code);
            return MobileDeviceManagementUtil.convertToFeature(mobileFeature);
        } catch (MobileDeviceManagementDAOException e) {
            throw new DeviceManagementException("Error occurred while retrieving the feature", e);
        }
    }

    public List<Feature> getFeatures() throws DeviceManagementException {

        List<Feature> featureList = new ArrayList<Feature>();
        try {
            List<MobileFeature> mobileFeatures = featureDAO.getAllFeatures();

            for (MobileFeature mobileFeature : mobileFeatures) {
                featureList.add(MobileDeviceManagementUtil.convertToFeature(mobileFeature));
            }
            return featureList;
        } catch (MobileDeviceManagementDAOException e) {
            throw new DeviceManagementException("Error occurred while retrieving the list of features registered " +
                    "for iOS platform", e);
        }
    }

    public boolean removeFeature(String name) throws DeviceManagementException {
        try {
            IOSDAOFactory.beginTransaction();
            featureDAO.deleteFeatureByCode(name);
            IOSDAOFactory.commitTransaction();
            return true;
        } catch (MobileDeviceManagementDAOException e) {
            try {
                IOSDAOFactory.rollbackTransaction();
            } catch (MobileDeviceManagementDAOException e1) {
                log.warn("Error occurred while roll-backing the transaction", e);
            }
            throw new DeviceManagementException("Error occurred while removing the feature", e);
        }
    }

    @Override
    public boolean addFeatures(List<Feature> features) throws DeviceManagementException {
        List<MobileFeature> mobileFeatures = new ArrayList<MobileFeature>();
        for (Feature feature : features) {
            mobileFeatures.add(MobileDeviceManagementUtil.convertToMobileFeature(feature));
        }
        try {
            IOSDAOFactory.beginTransaction();
            featureDAO.addFeatures(mobileFeatures);
            IOSDAOFactory.commitTransaction();
            return true;
        } catch (MobileDeviceManagementDAOException e) {
            try {
                IOSDAOFactory.rollbackTransaction();
            } catch (MobileDeviceManagementDAOException e1) {
                log.warn("Error occurred while roll-backing the transaction", e);
            }
            throw new DeviceManagementException("Error occurred while adding the features", e);
        }
    }

    @Override
    public boolean addSupportedFeaturesToDB() throws DeviceManagementException {
        synchronized (this) {
            List<Feature> supportedFeatures = getSupportedFeatures();
            List<Feature> existingFeatures = this.getFeatures();
            List<Feature> missingFeatures = MobileDeviceManagementUtil.
                                                         getMissingFeatures(supportedFeatures, existingFeatures);
            if (missingFeatures.size() > 0) {
                return this.addFeatures(missingFeatures);
            }
            return true;
        }
    }

    //Get the supported feature list.
    private static List<Feature> getSupportedFeatures() {
        List<Feature> supportedFeatures = new ArrayList<Feature>();
        Feature feature = new Feature();
        feature.setCode("INSTALL_ENTERPRISE_APPLICATION");
        feature.setName("Install Enterprise App");
        feature.setDescription("Install Enterprise App");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("INSTALL_STORE_APPLICATION");
        feature.setName("Install Public App");
        feature.setDescription("Install Public App");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("REMOVE_APPLICATION");
        feature.setName("Uninstall App");
        feature.setDescription("Uninstall App");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("DEVICE_LOCK");
        feature.setName("Device Lock");
        feature.setDescription("Device Lock");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("CELLULAR");
        feature.setName("Cellular");
        feature.setDescription("Cellular");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("APN");
        feature.setName("APN");
        feature.setDescription("APN");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("DOMAIN");
        feature.setName("DOMAIN");
        feature.setDescription("Domain operation");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("RESTRICTION");
        feature.setName("Restrictions");
        feature.setDescription("Restrictions operation");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("WIFI");
        feature.setName("Wifi");
        feature.setDescription("Wifi");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("DEVICE_INFO");
        feature.setName("Device Info");
        feature.setDescription("Device info operation");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("AIR_PLAY");
        feature.setName("Air Play");
        feature.setDescription("Air Play");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("LOCATION");
        feature.setName("Location");
        feature.setDescription("Fetch location");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("RING");
        feature.setName("Ring");
        feature.setDescription("Ring device");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("APPLICATION_LIST");
        feature.setName("Application list");
        feature.setDescription("Application list");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("PROFILE_LIST");
        feature.setName("Profile List");
        feature.setDescription("Profile list");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("REMOVE_PROFILE");
        feature.setName("Remove Profile");
        feature.setDescription("Remove profile");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("CLEAR_PASSCODE");
        feature.setName("Clear Passcode");
        feature.setDescription("Clear passcode");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("CALDAV");
        feature.setName("CalDev");
        feature.setDescription("Setup CalDav");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("CLEAR_PASSCODE");
        feature.setName("Clear Passcode");
        feature.setDescription("Clear passcode");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("CALENDAR_SUBSCRIPTION");
        feature.setName("Calendar Subscriptions");
        feature.setDescription("Calendar subscription");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("PASSCODE_POLICY");
        feature.setName("Passcode Policy");
        feature.setDescription("Passcode Policy");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("EMAIL");
        feature.setName("Email");
        feature.setDescription("Email operation");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("LDAP");
        feature.setName("LDAP");
        feature.setDescription("LDAP operation");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("WEB_CLIP");
        feature.setName("Web Clip");
        feature.setDescription("Web clip operation");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("VPN");
        feature.setName("VPN");
        feature.setDescription("VPN operation");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("PER_APP_VPN");
        feature.setName("Per App VPN");
        feature.setDescription("Per app VPN operation");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("APP_TO_PER_APP_VPN_MAPPING");
        feature.setName("VPN App mapping");
        feature.setDescription("App to per app VPN mapping operation");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("ENTERPRISE_WIPE");
        feature.setName("Enterprise Wipe");
        feature.setDescription("Enterprise wipe operation");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("APP_LOCK");
        feature.setName("App lock");
        feature.setDescription("App lock operation");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("GET_RESTRICTIONS");
        feature.setName("Get restrictions");
        feature.setDescription("Get restrictions operation");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("NOTIFICATION");
        feature.setName("Send notification");
        feature.setDescription("Send notification operation");
        supportedFeatures.add(feature);

        feature = new Feature();
        feature.setCode("WIPE_DATA");
        feature.setName("Wipe data");
        feature.setDescription("Factory reset the device");
        supportedFeatures.add(feature);

        return supportedFeatures;

    }
}
