/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * 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.
 */

package android.printservice;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;

/**
 * This class describes a {@link PrintService}. A print service knows
 * how to communicate with one or more printers over one or more protocols
 * and exposes printers for use by the applications via the platform print
 * APIs.
 *
 * @see PrintService
 * @see android.print.PrintManager
 *
 * @hide
 */
@SystemApi
public final class PrintServiceInfo implements Parcelable {

    private static final String LOG_TAG = PrintServiceInfo.class.getSimpleName();

    private static final String TAG_PRINT_SERVICE = "print-service";

    private final String mId;

    private boolean mIsEnabled;

    private final ResolveInfo mResolveInfo;

    private final String mSettingsActivityName;

    private final String mAddPrintersActivityName;

    private final String mAdvancedPrintOptionsActivityName;

    /**
     * Creates a new instance.
     *
     * @hide
     */
    public PrintServiceInfo(Parcel parcel) {
        mId = parcel.readString();
        mIsEnabled = parcel.readByte() != 0;
        mResolveInfo = parcel.readParcelable(null);
        mSettingsActivityName = parcel.readString();
        mAddPrintersActivityName = parcel.readString();
        mAdvancedPrintOptionsActivityName = parcel.readString();
    }

    /**
     * Creates a new instance.
     *
     * @param resolveInfo The service resolve info.
     * @param settingsActivityName Optional settings activity name.
     * @param addPrintersActivityName Optional add printers activity name.
     * @param advancedPrintOptionsActivityName Optional advanced print options activity.
     *
     * @hide
     */
    public PrintServiceInfo(ResolveInfo resolveInfo, String settingsActivityName,
            String addPrintersActivityName, String advancedPrintOptionsActivityName) {
        mId = new ComponentName(resolveInfo.serviceInfo.packageName,
                resolveInfo.serviceInfo.name).flattenToString();
        mResolveInfo = resolveInfo;
        mSettingsActivityName = settingsActivityName;
        mAddPrintersActivityName = addPrintersActivityName;
        mAdvancedPrintOptionsActivityName = advancedPrintOptionsActivityName;
    }

    /**
     * Return the component name for this print service.
     *
     * @return The component name for this print service.
     */
    public @NonNull ComponentName getComponentName() {
        return new ComponentName(mResolveInfo.serviceInfo.packageName,
                mResolveInfo.serviceInfo.name);
    }

    /**
     * Creates a new instance.
     *
     * @param context Context for accessing resources.
     * @param resolveInfo The service resolve info.
     * @return The created instance.
     *
     * @hide
     */
    public static PrintServiceInfo create(Context context, ResolveInfo resolveInfo) {
        String settingsActivityName = null;
        String addPrintersActivityName = null;
        String advancedPrintOptionsActivityName = null;

        XmlResourceParser parser = null;
        PackageManager packageManager = context.getPackageManager();
        parser = resolveInfo.serviceInfo.loadXmlMetaData(packageManager,
                PrintService.SERVICE_META_DATA);
        if (parser != null) {
            try {
                int type = 0;
                while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) {
                    type = parser.next();
                }

                String nodeName = parser.getName();
                if (!TAG_PRINT_SERVICE.equals(nodeName)) {
                    Log.e(LOG_TAG, "Ignoring meta-data that does not start with "
                            + TAG_PRINT_SERVICE + " tag");
                } else {
                    Resources resources = packageManager.getResourcesForApplication(
                            resolveInfo.serviceInfo.applicationInfo);
                    AttributeSet allAttributes = Xml.asAttributeSet(parser);
                    TypedArray attributes = resources.obtainAttributes(allAttributes,
                            com.android.internal.R.styleable.PrintService);

                    settingsActivityName = attributes.getString(
                            com.android.internal.R.styleable.PrintService_settingsActivity);

                    addPrintersActivityName = attributes.getString(
                            com.android.internal.R.styleable.PrintService_addPrintersActivity);

                    advancedPrintOptionsActivityName = attributes.getString(com.android.internal
                            .R.styleable.PrintService_advancedPrintOptionsActivity);

                    attributes.recycle();
                }
            } catch (IOException ioe) {
                Log.w(LOG_TAG, "Error reading meta-data:" + ioe);
            } catch (XmlPullParserException xppe) {
                Log.w(LOG_TAG, "Error reading meta-data:" + xppe);
            } catch (NameNotFoundException e) {
                Log.e(LOG_TAG, "Unable to load resources for: "
                        + resolveInfo.serviceInfo.packageName);
            } finally {
                if (parser != null) {
                    parser.close();
                }
            }
        }

        return new PrintServiceInfo(resolveInfo, settingsActivityName,
                addPrintersActivityName, advancedPrintOptionsActivityName);
    }

    /**
     * The accessibility service id.
     * <p>
     * <strong>Generated by the system.</strong>
     * </p>
     *
     * @return The id.
     *
     * @hide
     */
    public String getId() {
        return mId;
    }

    /**
     * If the service was enabled when it was read from the system.
     *
     * @return The id.
     *
     * @hide
     */
    public boolean isEnabled() {
        return mIsEnabled;
    }

    /**
     * Mark a service as enabled or not
     *
     * @param isEnabled If the service should be marked as enabled.
     *
     * @hide
     */
    public void setIsEnabled(boolean isEnabled) {
        mIsEnabled = isEnabled;
    }

    /**
     * The service {@link ResolveInfo}.
     *
     * @return The info.
     *
     * @hide
     */
    public ResolveInfo getResolveInfo() {
        return mResolveInfo;
    }

    /**
     * The settings activity name.
     * <p>
     * <strong>Statically set from
     * {@link PrintService#SERVICE_META_DATA meta-data}.</strong>
     * </p>
     *
     * @return The settings activity name.
     *
     * @hide
     */
    public String getSettingsActivityName() {
        return mSettingsActivityName;
    }

    /**
     * The add printers activity name.
     * <p>
     * <strong>Statically set from
     * {@link PrintService#SERVICE_META_DATA meta-data}.</strong>
     * </p>
     *
     * @return The add printers activity name.
     *
     * @hide
     */
    public String getAddPrintersActivityName() {
        return mAddPrintersActivityName;
    }

    /**
     * The advanced print options activity name.
     * <p>
     * <strong>Statically set from
     * {@link PrintService#SERVICE_META_DATA meta-data}.</strong>
     * </p>
     *
     * @return The advanced print options activity name.
     *
     * @hide
     */
    public String getAdvancedOptionsActivityName() {
        return mAdvancedPrintOptionsActivityName;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int flagz) {
        parcel.writeString(mId);
        parcel.writeByte((byte)(mIsEnabled ? 1 : 0));
        parcel.writeParcelable(mResolveInfo, 0);
        parcel.writeString(mSettingsActivityName);
        parcel.writeString(mAddPrintersActivityName);
        parcel.writeString(mAdvancedPrintOptionsActivityName);
    }

    @Override
    public int hashCode() {
        return 31 + ((mId == null) ? 0 : mId.hashCode());
    }

    @Override
    public boolean equals(@Nullable Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        PrintServiceInfo other = (PrintServiceInfo) obj;
        if (mId == null) {
            if (other.mId != null) {
                return false;
            }
        } else if (!mId.equals(other.mId)) {
            return false;
        }
        return true;
    }

    @NonNull
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("PrintServiceInfo{");
        builder.append("id=").append(mId);
        builder.append("isEnabled=").append(mIsEnabled);
        builder.append(", resolveInfo=").append(mResolveInfo);
        builder.append(", settingsActivityName=").append(mSettingsActivityName);
        builder.append(", addPrintersActivityName=").append(mAddPrintersActivityName);
        builder.append(", advancedPrintOptionsActivityName=")
                .append(mAdvancedPrintOptionsActivityName);
        builder.append("}");
        return builder.toString();
    }

    public static final @android.annotation.NonNull Parcelable.Creator<PrintServiceInfo> CREATOR =
            new Parcelable.Creator<PrintServiceInfo>() {
        @Override
        public PrintServiceInfo createFromParcel(Parcel parcel) {
            return new PrintServiceInfo(parcel);
        }

        @Override
        public PrintServiceInfo[] newArray(int size) {
            return new PrintServiceInfo[size];
        }
    };
}
