package com.avg.zaap.crashlibrary.provider.device;

import android.os.Build;
import android.support.annotation.NonNull;

import com.avg.zaap.crashlibrary.core.logger.CrashLogger;
import com.avg.zaap.crashlibrary.core.writer.DataWriterException;
import com.avg.zaap.crashlibrary.core.writer.IDataWriter;
import com.avg.zaap.crashlibrary.provider.CrashProviderException;
import com.avg.zaap.crashlibrary.provider.ICrashAsyncProvider;
import com.avg.zaap.crashlibrary.provider.ICrashProviderCallback;

import java.io.File;

/**
 * Asynchronous provider for information about device.
 * <p>
 * Created by marek.osvald on 21.4.2016.
 */
public class DeviceInfoProvider implements ICrashAsyncProvider {

    private static final String TAG = DeviceInfoProvider.class.getSimpleName();

    private static final String FILE_NAME = "DeviceInfo.txt";
    private static final String FORMATTER = "%-20s";

    private IDataWriter mDataWriter;

    /**
     * Default constructor. Uses default dependency factory.
     */
    @SuppressWarnings("unused")
    public DeviceInfoProvider() {
        this(new DeviceInfoProviderFactory());
    }

    /**
     * Parametric constructor. Sets the dependency factory to be used.
     *
     * @param factory dependency factory to use
     */
    public DeviceInfoProvider(IDeviceInfoProviderFactory factory) {
        mDataWriter = factory.getDataWriter();
    }

    @Override
    public void provideData(@NonNull String directory, @NonNull ICrashProviderCallback callback) {
        StringBuilder sb = new StringBuilder();

        //@formatter:off
        sb.append(String.format(FORMATTER, "Board: "       )).append(Build.BOARD          ).append('\n')
          .append(String.format(FORMATTER, "Bootloader: "  )).append(Build.BOOTLOADER     ).append('\n')
          .append(String.format(FORMATTER, "Brand: "       )).append(Build.BRAND          ).append('\n')
          .append(String.format(FORMATTER, "Device: "      )).append(Build.DEVICE         ).append('\n')
          .append(String.format(FORMATTER, "Display: "     )).append(Build.DISPLAY        ).append('\n')
          .append(String.format(FORMATTER, "HW: "          )).append(Build.HARDWARE       ).append('\n')
          .append(String.format(FORMATTER, "Host: "        )).append(Build.HOST           ).append('\n')
          .append(String.format(FORMATTER, "ID: "          )).append(Build.ID             ).append('\n')
          .append(String.format(FORMATTER, "Manufacturer: ")).append(Build.MANUFACTURER   ).append('\n')
          .append(String.format(FORMATTER, "Model: "       )).append(Build.MODEL          ).append('\n')
          .append(String.format(FORMATTER, "Product: "     )).append(Build.PRODUCT        ).append('\n')
          .append(String.format(FORMATTER, "SDK:    "      )).append(Build.VERSION.SDK_INT).append('\n')
          .append(String.format(FORMATTER, "Serial: "      )).append(Build.SERIAL         ).append('\n')
          .append(String.format(FORMATTER, "Tags: "        )).append(Build.TAGS           ).append('\n')
          .append(String.format(FORMATTER, "Type: "        )).append(Build.TYPE           ).append('\n')
          .append(String.format(FORMATTER, "User: "        )).append(Build.USER           ).append('\n');
        //@formatter:on

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            StringBuilder sbAbi = new StringBuilder();
            sbAbi.append(String.format(FORMATTER, "ABIs: "));
            for (String abi : Build.SUPPORTED_ABIS) {
                sbAbi.append(abi).append(", ");
            }

            //remove last empty character to better readability and testing
            sbAbi.delete(sbAbi.length() - 2, sbAbi.length());
            sb.append(sbAbi.toString()).append('\n');
        } else {
            //@formatter:off
            //noinspection deprecation
            sb.append(String.format(FORMATTER, "ABIs: "))
              .append(Build.CPU_ABI)
              .append(", ")
              .append(Build.CPU_ABI2)
              .append('\n');
            //@formatter:on
        }

        String path = directory + File.separatorChar + FILE_NAME;

        try {
            mDataWriter.write(path, sb.toString());
            callback.onSuccess(path);
        } catch (DataWriterException e) {
            CrashLogger.e(TAG, "Can't write info about device to file: %s", e.getMessage());
            callback.onFailure(TAG, new CrashProviderException("Can't write info about device to file", e));
        }
    }

}
